ZQuest Classic Coverage Report


Directory: src/
File: src/zq/zq_tiles.cpp
Date: 2025-11-13 04:25:43
Exec Total Coverage
Lines: 99 7697 1.3%
Functions: 1 201 0.5%
Branches: 14 6797 0.2%

Line Branch Exec Source
1 #include <cstring>
2 #include <cmath>
3
4 #include "base/files.h"
5 #include "base/qrs.h"
6 #include "base/dmap.h"
7 #include "base/cpool.h"
8 #include "base/autocombo.h"
9 #include "base/packfile.h"
10 #include "base/gui.h"
11 #include "base/combo.h"
12 #include "base/msgstr.h"
13 #include "base/zdefs.h"
14 #include "new_subscr.h"
15 #include "subscr.h"
16 #include "zq/zq_tiles.h"
17 #include "zq/zquest.h"
18 #include "tiles.h"
19 #include "zq/zq_misc.h"
20 #include "zq/zq_class.h"
21 #include "base/zsys.h"
22 #include "base/colors.h"
23 #include "base/qst.h"
24 #include "gui/jwin.h"
25 #include <base/new_menu.h>
26 #include "base/jwinfsel.h"
27 #include "hero_tiles.h"
28 #include "zq/questReport.h"
29 #include "dialog/info.h"
30 #include "dialog/scaletile.h"
31 #include "dialog/rotatetile.h"
32 #include "dialog/alert.h"
33 #include "drawing.h"
34 #include "colorname.h"
35 #include "zq/render.h"
36 #include "zinfo.h"
37 #include <fmt/format.h>
38 #include <functional>
39 #include "zq/moveinfo.h"
40 using std::set;
41
42
43 #ifdef _MSC_VER
44 #define stricmp _stricmp
45 #endif
46
47 #define HIDE_USED (show_only_unused_tiles&1)
48 #define HIDE_UNUSED (show_only_unused_tiles&2)
49 #define HIDE_BLANK (show_only_unused_tiles&4)
50 #define HIDE_8BIT_MARKER (show_only_unused_tiles&8)
51
52 extern void large_dialog(DIALOG *d);
53 static void massRecolorReset4Bit();
54 static void massRecolorReset8Bit();
55 static bool massRecolorSetup(int32_t cset);
56 static void massRecolorApply(int32_t tile);
57 extern int32_t last_droplist_sel;
58 extern int32_t TilePgCursorCol, CmbPgCursorCol;
59
60 int32_t ex=0;
61 int32_t nextcombo_fake_click=0;
62 int32_t invcol=0;
63 int32_t tthighlight = 1;
64 int32_t showcolortip = 1;
65 int32_t show_quartgrid = 0, hide_grid = 0;
66
67 tiledata *newundotilebuf;
68 std::vector<newcombo> undocombobuf;
69
70 BITMAP *selection_pattern;
71 byte selection_grid[18][18];
72 byte selection_anchor=0;
73
74 enum {selection_mode_normal, selection_mode_add, selection_mode_subtract, selection_mode_exclude};
75 BITMAP *selecting_pattern;
76 int32_t selecting_x1, selecting_x2, selecting_y1, selecting_y2;
77
78 extern int32_t bidcomboscripts_cnt;
79 extern script_struct bidcomboscripts[NUMSCRIPTSCOMBODATA];
80
81 BITMAP *intersection_pattern;
82
83 byte relational_template[48][4]=
84 {
85 { 0, 0, 0, 0 },
86 { 0, 1, 0, 0 },
87 { 1, 0, 0, 0 },
88 { 1, 1, 0, 0 },
89 { 0, 0, 1, 0 },
90 { 0, 1, 1, 0 },
91 { 1, 0, 1, 0 },
92 { 1, 1, 1, 0 },
93 { 0, 0, 0, 1 },
94 { 0, 1, 0, 1 },
95 { 1, 0, 0, 1 },
96 { 1, 1, 0, 1 },
97 { 0, 0, 1, 1 },
98 { 0, 1, 1, 1 },
99 { 1, 0, 1, 1 },
100 { 1, 1, 1, 1 },
101 { 0, 2, 0, 2 },
102 { 1, 2, 0, 2 },
103 { 0, 2, 1, 2 },
104 { 1, 2, 1, 2 },
105 { 3, 3, 0, 0 },
106 { 3, 3, 1, 0 },
107 { 3, 3, 0, 1 },
108 { 3, 3, 1, 1 },
109 { 3, 4, 0, 2 },
110 { 3, 4, 1, 2 },
111 { 2, 0, 2, 0 },
112 { 2, 1, 2, 0 },
113 { 2, 0, 2, 1 },
114 { 2, 1, 2, 1 },
115 { 2, 2, 2, 2 },
116 { 4, 3, 2, 0 },
117 { 4, 3, 2, 1 },
118 { 4, 4, 2, 2 },
119 { 0, 0, 3, 3 },
120 { 0, 1, 3, 3 },
121 { 1, 0, 3, 3 },
122 { 1, 1, 3, 3 },
123 { 0, 2, 3, 4 },
124 { 1, 2, 3, 4 },
125 { 3, 3, 3, 3 },
126 { 3, 4, 3, 4 },
127 { 2, 0, 4, 3 },
128 { 2, 1, 4, 3 },
129 { 2, 2, 4, 4 },
130 { 4, 3, 4, 3 },
131 { 4, 4, 4, 4 },
132 { 5, 5, 5, 5 }
133 };
134
135 byte dungeon_carving_template[96][4]=
136 {
137 { 0, 0, 0, 0 },
138 { 0, 1, 0, 0 },
139 { 1, 0, 0, 0 },
140 { 1, 1, 0, 0 },
141 { 0, 0, 1, 0 },
142 { 0, 1, 1, 0 },
143 { 1, 0, 1, 0 },
144 { 1, 1, 1, 0 },
145 { 0, 0, 0, 1 },
146 { 0, 1, 0, 1 },
147 { 1, 0, 0, 1 },
148 { 1, 1, 0, 1 },
149 { 0, 0, 1, 1 },
150 { 0, 1, 1, 1 },
151 { 1, 0, 1, 1 },
152 { 1, 1, 1, 1 },
153 { 0, 2, 0, 2 },
154 { 1, 2, 0, 2 },
155 { 0, 2, 1, 2 },
156 { 1, 2, 1, 2 },
157 { 3, 3, 0, 0 },
158 { 3, 3, 1, 0 },
159 { 3, 3, 0, 1 },
160 { 3, 3, 1, 1 },
161 { 3, 4, 0, 2 },
162 { 3, 4, 1, 2 },
163 { 2, 0, 2, 0 },
164 { 2, 1, 2, 0 },
165 { 2, 0, 2, 1 },
166 { 2, 1, 2, 1 },
167 { 2, 2, 2, 2 },
168 { 4, 3, 2, 0 },
169 { 4, 3, 2, 1 },
170 { 4, 4, 2, 2 },
171 { 0, 0, 3, 3 },
172 { 0, 1, 3, 3 },
173 { 1, 0, 3, 3 },
174 { 1, 1, 3, 3 },
175 { 0, 2, 3, 4 },
176 { 1, 2, 3, 4 },
177 { 3, 3, 3, 3 },
178 { 3, 4, 3, 4 },
179 { 2, 0, 4, 3 },
180 { 2, 1, 4, 3 },
181 { 2, 2, 4, 4 },
182 { 4, 3, 4, 3 },
183 { 4, 4, 4, 4 },
184 { 5, 5, 5, 5 },
185
186 { 5, 5, 5, 5 },
187 { 6, 6, 6, 6 },
188 { 7, 7, 7, 7 },
189 { 7, 6, 7, 6 },
190 { 8, 8, 8, 8 },
191 { 16, 6, 8, 15 },
192 { 7, 7, 8, 8 },
193 { 7, 6, 8, 15 },
194 { 9, 9, 9, 9 },
195 { 6, 6, 9, 9 },
196 { 7, 17, 14, 9 },
197 { 7, 6, 14, 9 },
198 { 8, 9, 8, 9 },
199 { 16, 6, 8, 9 },
200 { 7, 17, 8, 9 },
201 { 7, 6, 8, 9 },
202 { 10, 10, 10, 10 },
203 { 7, 10, 14, 10 },
204 { 16, 10, 8, 10 },
205 { 7, 10, 8, 10 },
206 { 11, 11, 11, 11 },
207 { 11, 11, 8, 15 },
208 { 11, 11, 14, 9 },
209 { 11, 11, 8, 9 },
210 { 14, 14, 14, 14 },
211 { 14, 14, 8, 14 },
212 { 12, 12, 12, 12 },
213 { 12, 6, 12, 15 },
214 { 12, 17, 12, 9 },
215 { 12, 6, 12, 9 },
216 { 12, 10, 12, 10 },
217 { 15, 15, 15, 15 },
218 { 15, 15, 15, 9 },
219 { 15, 14, 12, 10 },
220 { 13, 13, 13, 13 },
221 { 16, 6, 13, 13 },
222 { 7, 17, 13, 13 },
223 { 7, 6, 13, 13 },
224 { 16, 16, 16, 16 },
225 { 7, 16, 16, 16 },
226 { 11, 11, 13, 13 },
227 { 11, 14, 13, 16 },
228 { 17, 17, 17, 17 },
229 { 17, 6, 17, 17 },
230 { 12, 10, 17, 16 },
231 { 15, 11, 17, 13 },
232 { 15, 14, 17, 16 },
233 { 18, 18, 18, 18 }
234 };
235
236 struct tile_move_data
237 {
238 int32_t copies;
239 int32_t dest_first;
240 int32_t dest_last;
241 int32_t src_first;
242 int32_t src_last;
243 int32_t dest_top;
244 int32_t dest_bottom;
245 int32_t src_top;
246 int32_t src_bottom;
247 int32_t src_left, src_right;
248 int32_t src_width, src_height;
249 int32_t dest_left, dest_right;
250 int32_t dest_width, dest_height;
251 int32_t rows, cols;
252 bool rect, move;
253
254 tile_move_data()
255 {
256 copies = dest_first = dest_last = src_first = src_last = dest_top =
257 dest_bottom = src_top = src_bottom = src_left = src_right =
258 src_width = src_height = dest_left = dest_right = dest_width =
259 dest_height = rows = cols = 0;
260 rect = move = false;
261 }
262
263 tile_move_data(tile_move_data const& other)
264 {
265 copy(other);
266 }
267
268 tile_move_data& operator=(tile_move_data const& other)
269 {
270 copy(other);
271 return *this;
272 }
273
274 void copy(tile_move_data const& other)
275 {
276 copies = other.copies;
277 dest_first = other.dest_first;
278 dest_last = other.dest_last;
279 src_first = other.src_first;
280 src_last = other.src_last;
281 dest_top = other.dest_top;
282 dest_bottom = other.dest_bottom;
283 src_top = other.src_top;
284 src_bottom = other.src_bottom;
285 src_left = other.src_left;
286 src_right = other.src_right;
287 src_width = other.src_width;
288 src_height = other.src_height;
289 dest_left = other.dest_left;
290 dest_right = other.dest_right;
291 dest_width = other.dest_width;
292 dest_height = other.dest_height;
293 rows = other.rows;
294 cols = other.cols;
295 rect = other.rect;
296 move = other.move;
297 }
298
299 void flip()
300 {
301 zc_swap(src_first, dest_first);
302 zc_swap(src_last, dest_last);
303 zc_swap(src_top, dest_top);
304 zc_swap(src_bottom, dest_bottom);
305 zc_swap(src_left, dest_left);
306 zc_swap(src_right, dest_right);
307 zc_swap(src_width, dest_width);
308 zc_swap(src_height, dest_height);
309 }
310 };
311 bool do_movetile_united(tile_move_data const& tmd);
312
313 struct combo_move_data
314 {
315 int32_t tile, tile2, copy1, copycnt;
316 combo_move_data() : tile(0), tile2(0), copy1(0), copycnt(0){}
317 combo_move_data(combo_move_data const& other)
318 {
319 copy(other);
320 }
321 combo_move_data& operator=(combo_move_data const& other)
322 {
323 copy(other);
324 return *this;
325 }
326 void copy(combo_move_data const& other)
327 {
328 tile = other.tile;
329 tile2 = other.tile2;
330 copy1 = other.copy1;
331 copycnt = other.copycnt;
332 }
333
334 void flip()
335 {
336 int32_t tcnt = tile2-tile+1;
337 int32_t cpy2 = copy1+copycnt-1;
338 zc_swap(tile,copy1);
339 tile2 = cpy2;
340 copycnt = tcnt;
341 }
342 };
343
344 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing = false);
345 static optional<ComboMoveUndo> last_combo_move_list;
346 static optional<TileMoveUndo> last_tile_move_list;
347
348 int refl_flags = 0;
349 enum
350 {
351 REFL_90CW, REFL_HFLIP,
352 REFL_90CCW, REFL_VFLIP,
353 REFL_180, REFL_DBLFLIP,
354 REFL_MAX
355 };
356 const char *reflbtn_names[] =
357 {
358 "90 CW", "HFlip",
359 "90 CCW", "VFlip",
360 "180 Rot", "Diag Flip"
361 };
362 int bgmode = 0, xmode = 0;
363 const char *bgmodebtn_names[] =
364 {
365 "BG Color 0", "BG Trans."
366 };
367 const char *xmodebtn_names[] =
368 {
369 "X", "No X"
370 };
371 enum
372 {
373 XMODE_X, XMODE_NOX,
374 XMODE_MAX
375 };
376 enum
377 {
378 BGMODE_0, BGMODE_TRANSP,
379 BGMODE_MAX
380 };
381
382 void merge_tiles(int32_t dest_tile, int32_t src_quarter1, int32_t src_quarter2, int32_t src_quarter3, int32_t src_quarter4)
383 {
384 int32_t size=tilesize(newtilebuf[dest_tile].format)>>4;
385 int32_t size2=size>>1;
386
387 if(newtilebuf[dest_tile].data==NULL)
388 {
389 reset_tile(newtilebuf, dest_tile, newtilebuf[src_quarter1>>2].format);
390 }
391
392 int32_t i=0;
393
394 if((dest_tile<<2)+i!=src_quarter1)
395 {
396 for(int32_t j=0; j<8; ++j)
397 {
398 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter1>>2].data[((j+((src_quarter1&2)<<2))*size)+((src_quarter1&1)*size2)]), size2);
399 }
400 }
401
402 i=1;
403
404 if((dest_tile<<2)+i!=src_quarter2)
405 {
406 for(int32_t j=0; j<8; ++j)
407 {
408 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter2>>2].data[((j+((src_quarter2&2)<<2))*size)+((src_quarter2&1)*size2)]), size2);
409 }
410 }
411
412 i=2;
413
414 if((dest_tile<<2)+i!=src_quarter3)
415 {
416 for(int32_t j=0; j<8; ++j)
417 {
418 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter3>>2].data[((j+((src_quarter3&2)<<2))*size)+((src_quarter3&1)*size2)]), size2);
419 }
420 }
421
422 i=3;
423
424 if((dest_tile<<2)+i!=src_quarter4)
425 {
426 for(int32_t j=0; j<8; ++j)
427 {
428 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter4>>2].data[((j+((src_quarter4&2)<<2))*size)+((src_quarter4&1)*size2)]), size2);
429 }
430 }
431 }
432
433 static void make_combos(int32_t startTile, int32_t endTile, int32_t cs)
434 {
435 al_trace("inside make_combos()\n");
436 int32_t startCombo=0;
437
438 if(!select_combo_2(startCombo,cs))
439 return;
440
441 int32_t temp=combobuf[startCombo].o_tile;
442 combobuf[startCombo].set_tile(startTile);
443
444 if(!edit_combo(startCombo, false, cs))
445 {
446 combobuf[startCombo].set_tile(temp);
447 return;
448 }
449
450 go_combos();
451
452 for(int32_t i=0; i<=endTile-startTile; i++)
453 {
454 combobuf[startCombo+i]=combobuf[startCombo];
455 combobuf[startCombo+i].set_tile(startTile+i);
456 }
457
458 setup_combo_animations();
459 setup_combo_animations2();
460 }
461
462 static void make_combos_rect(int32_t top, int32_t left, int32_t numRows, int32_t numCols, int32_t cs)
463 {
464 int32_t startCombo=0;
465
466 if(!select_combo_2(startCombo, cs))
467 return;
468
469 int32_t startTile=top*TILES_PER_ROW+left;
470 int32_t temp=combobuf[startCombo].o_tile;
471 combobuf[startCombo].set_tile(startTile);
472
473 if(!edit_combo(startCombo, false, cs))
474 {
475 al_trace("make_combos_rect() early return\n");
476 combobuf[startCombo].set_tile(temp);
477 return;
478 }
479
480 bool smartWrap=false;
481 if(numCols!=4 && numRows>1)
482 {
483 char buf[64];
484 if(numCols<4)
485 sprintf(buf, "Limit to %d column%s?", numCols, numCols==1 ? "" : "s");
486 else
487 sprintf(buf, "Fit to 4 columns?"); // Meh, whatever.
488 int32_t ret=jwin_alert("Wrapping", buf, NULL, NULL, "&Yes", "&No", 'y', 'n', get_zc_font(font_lfont));
489 if(ret==1)
490 smartWrap=true;
491 }
492
493 go_combos();
494
495 int32_t combo=startCombo-1;
496 for(int32_t row=0; row<numRows; row++)
497 {
498 for(int32_t col=0; col<numCols; col++)
499 {
500 int32_t tile=startTile+row*TILES_PER_ROW+col;
501 if(smartWrap)
502 // Add 4 per row, and another numRows*4 for every 4 columns
503 // (col&0xFC==col/4*4), and then the column %4
504 combo=startCombo+4*row+(col&0xFC)*numRows+col%4;
505 else
506 combo++;
507
508 combobuf[combo]=combobuf[startCombo];
509 combobuf[combo].set_tile(tile);
510 }
511 }
512
513 setup_combo_animations();
514 setup_combo_animations2();
515 }
516
517 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t c);
518
519 static bool nogotiles = false;
520 static bool nogocombos = false;
521
522 void go_tiles()
523 {
524 if(nogotiles) return;
525 last_tile_move_list = nullopt;
526 for(int32_t i=0; i<NEWMAXTILES; ++i)
527 {
528 newundotilebuf[i].format=newtilebuf[i].format;
529
530 if(newundotilebuf[i].data!=NULL)
531 {
532 free(newundotilebuf[i].data);
533 }
534
535 newundotilebuf[i].data=(byte *)malloc(tilesize(newundotilebuf[i].format));
536
537 if(newundotilebuf[i].data==NULL)
538 {
539 Z_error_fatal("Unable to initialize undo tile #%ld.\n", i);
540 }
541
542 memcpy(newundotilebuf[i].data,newtilebuf[i].data,tilesize(newundotilebuf[i].format));
543 }
544 }
545
546 void go_slide_tiles(int32_t columns, int32_t rows, int32_t top, int32_t left)
547 {
548 for(int32_t c=0; c<columns; c++)
549 {
550 for(int32_t r=0; r<rows; r++)
551 {
552 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
553 newundotilebuf[t].format=newtilebuf[t].format;
554
555 if(newundotilebuf[t].data!=NULL)
556 {
557 free(newundotilebuf[t].data);
558 }
559
560 newundotilebuf[t].data=(byte *)malloc(tilesize(newundotilebuf[t].format));
561
562 if(newundotilebuf[t].data==NULL)
563 {
564 Z_error_fatal("Unable to initialize undo tile #%ld.\n", t);
565 }
566
567 memcpy(newundotilebuf[t].data,newtilebuf[t].data,tilesize(newundotilebuf[t].format));
568 }
569 }
570 }
571
572 void comeback_tiles()
573 {
574 if(last_tile_move_list)
575 {
576 last_tile_move_list->undo();
577 last_tile_move_list = nullopt;
578 }
579 for(dword i=0; i<NEWMAXTILES; ++i)
580 {
581 if(newtilebuf[i].format != newundotilebuf[i].format || !newtilebuf[i].data)
582 {
583 newtilebuf[i].format = newundotilebuf[i].format;
584
585 if(newtilebuf[i].data!=NULL)
586 free(newtilebuf[i].data);
587 newtilebuf[i].data=(byte *)malloc(tilesize(newtilebuf[i].format));
588 if(newtilebuf[i].data==NULL)
589 Z_error_fatal("Unable to initialize tile #%ld.\n", i);
590 }
591
592 memcpy(newtilebuf[i].data,newundotilebuf[i].data,tilesize(newtilebuf[i].format));
593 }
594
595 register_blank_tiles();
596 register_used_tiles();
597 }
598
599 void go_combos()
600 {
601 if(nogocombos) return;
602 last_combo_move_list = nullopt;
603
604 undocombobuf = combobuf;
605 }
606
607 void comeback_combos()
608 {
609 if(last_combo_move_list)
610 {
611 last_combo_move_list->undo();
612 last_combo_move_list = nullopt;
613 }
614
615 combobuf = undocombobuf;
616 }
617
618 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t s)
619 {
620 line(dest,x,y,x+s,y+s,c);
621 line(dest,x+s,y,x,y+s,c);
622 }
623 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t w, int32_t h)
624 {
625 line(dest,x,y,x+w,y+h,c);
626 line(dest,x+w,y,x,y+h,c);
627 }
628
629 enum {gm_light, gm_dark, gm_max};
630 int32_t gridmode=gm_light;
631
632 bool has_selection()
633 {
634 for(int32_t i=1; i<17; ++i)
635 {
636 for(int32_t j=1; j<17; ++j)
637 {
638 if(selection_grid[i][j])
639 {
640 return true;
641 }
642 }
643 }
644
645 return false;
646 }
647
648 void draw_selection_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
649 {
650 drawing_mode(DRAW_MODE_COPY_PATTERN, selection_pattern, selection_anchor>>3, 0);
651
652 for(int32_t i=1; i<18; ++i)
653 {
654 for(int32_t j=1; j<18; ++j)
655 {
656 // zoomtile16(screen2,tile,79,31,cs,flip,8);
657 if(selection_grid[i-1][j]!=selection_grid[i][j])
658 {
659 vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
660 }
661
662 if(selection_grid[i][j-1]!=selection_grid[i][j])
663 {
664 hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
665 }
666 }
667 }
668
669 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
670 // selection_anchor=(selection_anchor+1)%64;
671 }
672
673 bool is_selecting()
674 {
675 return (selecting_x1>-1&&selecting_x2>-1&&selecting_y1>-1&&selecting_y2>-1);
676 }
677
678 void draw_selecting_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
679 {
680 int32_t x1=zc_min(selecting_x1,selecting_x2);
681 int32_t x2=zc_max(selecting_x1,selecting_x2);
682 int32_t y1=zc_min(selecting_y1,selecting_y2);
683 int32_t y2=zc_max(selecting_y1,selecting_y2);
684
685 // rect(dest, x+(x1*scale2), y+(y1*scale2), x+((x2+1)*scale2), y+((y2+1)*scale2), 255);
686 for(int32_t i=1; i<18; ++i)
687 {
688 for(int32_t j=1; j<18; ++j)
689 {
690 drawing_mode(DRAW_MODE_COPY_PATTERN, selecting_pattern, selection_anchor>>3, 0);
691
692 if(((j>=y1+1)&&(j<=y2+1))&&((i==x1+1)||(i==x2+2)))
693 {
694 if(selection_grid[i-1][j]!=selection_grid[i][j])
695 {
696 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
697 }
698
699 vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
700 }
701
702 if(((i>=x1+1)&&(i<=x2+1))&&((j==y1+1)||(j==y2+2)))
703 {
704 if(selection_grid[i][j-1]!=selection_grid[i][j])
705 {
706 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
707 }
708
709 hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
710 }
711 }
712 }
713
714 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
715 // selection_anchor=(selection_anchor+1)%64;
716 }
717
718 void unfloat_selection();
719 bool floating_sel = false;
720 byte floatsel[256];
721 byte undofloatsel[256];
722 bool undo_is_floatsel = false;
723
724
725 void add_color_to_selection(int32_t color)
726 {
727 unfloat_selection();
728 for(int32_t i=1; i<17; ++i)
729 {
730 for(int32_t j=1; j<17; ++j)
731 {
732 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
733 {
734 selection_grid[i][j]=1;
735 }
736 }
737 }
738 }
739
740 void remove_color_from_selection(int32_t color)
741 {
742 unfloat_selection();
743 for(int32_t i=1; i<17; ++i)
744 {
745 for(int32_t j=1; j<17; ++j)
746 {
747 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
748 {
749 selection_grid[i][j]=0;
750 }
751 }
752 }
753 }
754
755 void intersect_color_with_selection(int32_t color)
756 {
757 unfloat_selection();
758 for(int32_t i=1; i<17; ++i)
759 {
760 for(int32_t j=1; j<17; ++j)
761 {
762 if((unpackbuf[((j-1)<<4)+(i-1)]==color)&&(selection_grid[i][j]==1))
763 {
764 selection_grid[i][j]=1;
765 }
766 else
767 {
768 selection_grid[i][j]=0;
769 }
770 }
771 }
772 }
773
774 bool is_in_selection(int32_t x, int32_t y)
775 {
776 x %= 16; y %= 16;
777 if(x < 0) x = (16 - abs(x));
778 if(y < 0) y = (16 - abs(y));
779 return (!has_selection()||(selection_grid[x+1][y+1]!=0));
780 }
781
782 void zoomtile16(BITMAP *dest,int32_t tile,int32_t x,int32_t y,int32_t cset,int32_t flip,int32_t m)
783 {
784 // rectfill(dest,x,y,x+(16*m),y+(16*m),gridmode==gm_light?jwin_pal[jcMEDLT]:jwin_pal[jcDARK]);
785 int gridcol = gridmode==gm_light?vc(7):vc(8);
786
787 cset <<= 4;
788 if(newtilebuf[tile].format>tf4Bit)
789 cset=0;
790
791 int g = hide_grid ? 1 : 0;
792 byte transp_col = (bgmode == BGMODE_TRANSP ? jwin_pal[jcBOX] : 0+cset);
793 rectfill(dest,x,y,x+(16*m)+g,y+(16*m)+g,transp_col);
794
795 unpack_tile(newtilebuf, tile, 0, false);
796 byte *si = unpackbuf;
797 for(int32_t cy=0; cy<16; cy++)
798 {
799 for(int32_t cx=0; cx<16; cx++)
800 {
801 byte col = (floating_sel && floatsel[cx+(cy<<4)]) ? floatsel[cx+(cy<<4)] : *si;
802 int32_t dx = ((flip&1)?15-cx:cx)*m;
803 int32_t dy = ((flip&2)?15-cy:cy)*m;
804 if(col)
805 rectfill(dest,x+dx,y+dy,x+dx+m-1,y+dy+m-1,col+cset);
806
807 if(!col && xmode == XMODE_X)
808 little_x(dest,x+dx+m/4,y+dy+m/4,invcol,m/2);
809
810 ++si;
811 }
812 }
813
814 if(!hide_grid)
815 {
816 for(int cx = 0; cx <= 16; ++cx)
817 vline(dest,x+(cx*m),y,y+(16*m)-1,gridcol);
818 for(int cy = 0; cy <= 16; ++cy)
819 hline(dest,x,y+(cy*m),x+(16*m)-1,gridcol);
820 }
821
822 if(show_quartgrid)
823 {
824 int offs = (8*m);
825 const int RAD = 3;
826 rectfill(dest,x+offs-RAD,y,x+offs+RAD,y+(16*m),gridcol);
827 rectfill(dest,x,y+offs-RAD,x+(16*m),y+offs+RAD,gridcol);
828 }
829
830 if(has_selection()||is_selecting())
831 {
832 selection_anchor=(selection_anchor+1)%64;
833
834 if(has_selection()||is_selecting())
835 draw_selection_outline(dest, x, y, m);
836
837 if(is_selecting())
838 draw_selecting_outline(dest, x, y, m);
839 }
840 }
841
842 void draw_text_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,int32_t flags,bool jwin)
843 {
844 if(!jwin)
845 {
846 if(flags&D_SELECTED)
847 {
848 zc_swap(fg,bg);
849 }
850
851 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
852 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
853 rect(dest,x,y,x+w-2,y+h-2,fg);
854 textout_centre_ex(dest,font,text,(x+x+w)>>1,((y+y+h)>>1)-4,fg,-1);
855 }
856 else
857 {
858 jwin_draw_text_button(dest, x, y, w, h, text, flags, true);
859 }
860 }
861
862 void draw_icon_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,int icon,int32_t bg,int32_t fg,int32_t flags,bool jwin)
863 {
864 if(!jwin)
865 {
866 if(flags&D_SELECTED)
867 {
868 zc_swap(fg,bg);
869 }
870
871 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
872 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
873 rect(dest,x,y,x+w-2,y+h-2,fg);
874 jwin_draw_icon(dest,x+w/2,y+h/2,fg,icon,icon_proportion(icon,w,h),true);
875 }
876 else
877 {
878 jwin_draw_icon_button(dest, x, y, w, h, icon, flags, true);
879 }
880 }
881
882 void draw_layer_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t flags)
883 {
884 if(flags&D_SELECTED)
885 {
886 rect(dest, x, y, x+w-1, y+h-1, jwin_pal[jcDARK]);
887 ++x;
888 ++y;
889 --w;
890 --h;
891 }
892 rectfill(dest,x+1,y+1,x+w-3,y+h-3,jwin_pal[(flags&D_SELECTED ? jcMEDDARK : jcBOX)]);
893 jwin_draw_frame(dest, x, y, w, h, (flags&D_SELECTED ? FR_DARK : FR_BOX));
894
895 //Forcibly fit the text within the button
896 char buf[512] = {0};
897 strcpy(buf, text);
898
899 bool dis = (flags&D_DISABLED);
900 auto hei = text_height(font);
901 auto len = text_length(font,buf);
902 auto borderwid = 8;
903 if(len > w - borderwid + (dis ? 1 : 0))
904 {
905 auto ind = strlen(buf) - 1;
906 auto dotcount = 0;
907 while(len > w - borderwid + (dis ? 1 : 0))
908 {
909 if(dotcount >= 2)
910 buf[ind+2] = 0;
911 else ++dotcount;
912 buf[ind--] = '.';
913 len = text_length(font,buf);
914 }
915 }
916 if(dis)
917 {
918 ++len; ++hei;
919 }
920 BITMAP* tmp = create_bitmap_ex(8,len,hei);
921 clear_bitmap(tmp);
922 if(dis)
923 {
924 textout_ex(tmp,font,buf,1,1,jwin_pal[jcLIGHT],-1);
925 textout_ex(tmp,font,buf,0,0,jwin_pal[jcDISABLED_FG],-1);
926 }
927 else
928 textout_ex(tmp,font,buf,0,0,jwin_pal[jcBOXFG],-1);
929 auto tx = x+((w-len)/2);
930 auto ty = y+((h-hei)/2);
931 if(len > w-borderwid)
932 {
933 tx = x+borderwid/2;
934 len = w-borderwid;
935 }
936 if(hei > h-borderwid)
937 {
938 ty = y+borderwid/2;
939 hei = h-borderwid;
940 }
941 masked_blit(tmp,dest, 0,0, tx,ty, len, hei);
942 destroy_bitmap(tmp);
943 }
944
945 bool do_layer_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text, int32_t flags, bool toggleflag)
946 {
947 bool over=false;
948
949 while(gui_mouse_b())
950 {
951 //vsync();
952 if(mouse_in_rect(x,y,w,h))
953 {
954 if(!over)
955 {
956 vsync();
957 draw_layer_button(screen, x, y, w, h, text, flags^D_SELECTED);
958 over=true;
959
960 update_hw_screen();
961 }
962 }
963 else
964 {
965 if(over)
966 {
967 vsync();
968 draw_layer_button(screen, x, y, w, h, text, flags);
969 over=false;
970
971 update_hw_screen();
972 }
973 }
974 rest(1);
975 }
976
977 if(over)
978 {
979 vsync();
980 draw_layer_button(screen, x, y, w, h, text, toggleflag ? flags^D_SELECTED : flags);
981
982 update_hw_screen();
983 }
984
985 return over;
986 }
987
988 bool do_text_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,bool jwin, bool sel)
989 {
990 bool over=false;
991
992 while(gui_mouse_b())
993 {
994 custom_vsync();
995
996 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
997 {
998 if(!over)
999 {
1000 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1001 over=true;
1002 }
1003 }
1004 else
1005 {
1006 if(over)
1007 {
1008 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?D_SELECTED:0,jwin);
1009 over=false;
1010 }
1011 }
1012 }
1013
1014 if(over)
1015 {
1016 custom_vsync();
1017 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1018 }
1019
1020 return over;
1021 }
1022
1023 void draw_graphics_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,int32_t flags,bool jwin,bool overlay)
1024 {
1025 if(!jwin)
1026 {
1027 if(flags&D_SELECTED)
1028 {
1029 zc_swap(fg,bg);
1030 }
1031
1032 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
1033 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
1034 rect(dest,x,y,x+w-2,y+h-2,fg);
1035 int32_t g = (flags & D_SELECTED) ? 1 : 0;
1036
1037 if(overlay)
1038 {
1039 masked_blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1040 }
1041 else
1042 {
1043 blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1044 }
1045 }
1046 else
1047 {
1048 jwin_draw_graphics_button(dest, x, y, w, h, bmp, bmp2, flags, false, overlay);
1049 }
1050 }
1051
1052 bool do_graphics_button(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1053 {
1054 bool over=false;
1055
1056 while(gui_mouse_b())
1057 {
1058 custom_vsync();
1059
1060 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1061 {
1062 if(!over)
1063 {
1064 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1065 over=true;
1066 }
1067 }
1068 else
1069 {
1070 if(over)
1071 {
1072 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1073 over=false;
1074 }
1075 }
1076 }
1077
1078 return over;
1079 }
1080
1081 bool do_graphics_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1082 {
1083 bool over=false;
1084
1085 while(gui_mouse_b())
1086 {
1087 custom_vsync();
1088
1089 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1090 {
1091 if(!over)
1092 {
1093 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1094 over=true;
1095 }
1096 }
1097 else
1098 {
1099 if(over)
1100 {
1101 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1102 over=false;
1103 }
1104 }
1105 }
1106
1107 if(over)
1108 {
1109 custom_vsync();
1110 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1111 }
1112
1113 return over;
1114 }
1115 // circle(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1116 // circlefill(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1117
1118 void draw_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg, int32_t value)
1119 {
1120 //these are here to bypass compiler warnings about unused arguments
1121 bg=bg;
1122 fg=fg;
1123
1124 int32_t r, center;
1125
1126 for(int32_t k=0; k<7; k++)
1127 {
1128 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1129 {
1130 // circle(dest, x+(k*25)+4, y+4, 4, fg);
1131 // circlefill(dest, x+(k*25)+4, y+4, 2, (value==k)?fg:bg);
1132 //*
1133 r = 9/2;
1134
1135 center = x+(k*25)+r;
1136 rectfill(dest, x+(k*25), y, x+(k*25)+9-1, y+9-1, jwin_pal[jcBOX]);
1137
1138 circlefill(dest, center, y+r, r, jwin_pal[jcLIGHT]);
1139 arc(dest, center, y+r, itofix(32), itofix(160), r, jwin_pal[jcMEDDARK]);
1140 circlefill(dest, center, y+r, r-1, jwin_pal[jcMEDLT]);
1141 arc(dest, center, y+r, itofix(32), itofix(160), r-1, jwin_pal[jcDARK]);
1142 circlefill(dest, center, y+r, r-2, jwin_pal[jcLIGHT]);
1143
1144 if(value==k)
1145 {
1146 circlefill(dest, center, y+r, r-3, jwin_pal[jcDARK]);
1147 }
1148
1149 //*/
1150 }
1151 }
1152 }
1153
1154 void do_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg,int32_t &value)
1155 {
1156 while(gui_mouse_b())
1157 {
1158 custom_vsync();
1159
1160 for(int32_t k=0; k<7; k++)
1161 {
1162 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1163 {
1164 //if on radio button
1165 if(isinRect(gui_mouse_x(),gui_mouse_y(),x+(k*25),y,x+(k*25)+8,y+8))
1166 {
1167 value=k;
1168 draw_layerradio(dest,x,y,bg,fg,value);
1169 refresh(rMENU);
1170 }
1171 }
1172 }
1173 }
1174 }
1175
1176 //*************** tile flood fill stuff **************
1177
1178 byte tf_c;
1179 byte tf_u;
1180
1181 void tile_floodfill_rec(int32_t x,int32_t y)
1182 {
1183 if(is_in_selection(x,y))
1184 {
1185 while(x>0 && (unpackbuf[(y<<4)+x-1] == tf_u))
1186 --x;
1187
1188 while(x<=15 && (unpackbuf[(y<<4)+x] == tf_u))
1189 {
1190 if(is_in_selection(x,y))
1191 {
1192 unpackbuf[(y<<4)+x] = tf_c;
1193 }
1194
1195 if(y>0 && (unpackbuf[((y-1)<<4)+x] == tf_u))
1196 tile_floodfill_rec(x,y-1);
1197
1198 if(y<15 && (unpackbuf[((y+1)<<4)+x] == tf_u))
1199 tile_floodfill_rec(x,y+1);
1200
1201 ++x;
1202 }
1203 }
1204 }
1205
1206 void tile_floodfill(int32_t tile,int32_t x,int32_t y,byte c)
1207 {
1208 if(is_in_selection(x,y))
1209 {
1210 if(floating_sel)
1211 {
1212 memcpy(unpackbuf, floatsel, 256);
1213 }
1214 else unpack_tile(newtilebuf, tile, 0, false);
1215 tf_c = c;
1216 tf_u = unpackbuf[(y<<4)+x];
1217
1218 if(tf_u != tf_c)
1219 tile_floodfill_rec(x,y);
1220 if(floating_sel)
1221 {
1222 memcpy(floatsel, unpackbuf, 256);
1223 }
1224 else pack_tile(newtilebuf,unpackbuf,tile);
1225 }
1226 }
1227
1228 //***************** tile editor stuff *****************
1229 12 size_and_pos ok_button(302,562,71,21);
1230 12 size_and_pos cancel_button(376,562,71,21);
1231 12 size_and_pos edit_button(550,562,86,21);
1232 12 size_and_pos hlcbox(742,392,16,16);
1233 12 size_and_pos hov_prev(742,338,50,50);
1234 12 size_and_pos cpalette_4(648,416,4,4,64,64);
1235 12 size_and_pos cpalette_8(648,416,16,14,16,18);
1236 12 size_and_pos fg_prev(648,316,50,50);
1237 12 size_and_pos bg_prev(648+30,316+30,50,50);
1238 12 size_and_pos zoomtile(124,32,16,16,32,32);
1239 12 size_and_pos prev_til_1(648,31,96,96);
1240 12 size_and_pos prev_til_2(752,31,96,96);
1241 12 size_and_pos prev_til_3(648,135,96,96);
1242 12 size_and_pos prev_til_4(752,135,96,96);
1243 12 size_and_pos ref_til(14,189,96,96);
1244 12 size_and_pos status_info(648,308-(4*8),1,4,1,8);
1245 12 size_and_pos hover_info(742,338-(3*8),1,3,1,8);
1246 12 size_and_pos color_info(4,294,1,1,116,8);
1247 12 size_and_pos color_info_btn(24,294,96,21);
1248 12 size_and_pos tool_btns(22,29,2,4,39,39);
1249 12 size_and_pos x_btn(890,5,15,13);
1250 12 size_and_pos info_btn(872,5,15,13);
1251 12 size_and_pos hidegrid_cbox(124,552,16,16);
1252 12 size_and_pos quartgrid_cbox(124,572,16,16);
1253 12 size_and_pos reflbtn_grid(124,610,2,3,71,21);
1254 12 size_and_pos xmodebtn_grid(300,610,1,2,90,21);
1255 12 size_and_pos bgmodebtn_grid(390,610,1,2,90,21);
1256
1257 int32_t c1=1;
1258 int32_t c2=0;
1259 int32_t floating_tile = -1;
1260 int32_t tool = t_pen;
1261 int32_t old_tool = -1;
1262 int32_t tool_cur = -1;
1263 int32_t select_mode = 0;
1264 int32_t drawing=0;
1265 int32_t reftile = 0;
1266
1267 bool qgrid_tool(int tool)
1268 {
1269 switch(tool)
1270 {
1271 case t_pen:
1272 case t_fill:
1273 case t_recolor:
1274 case t_wand:
1275 return true;
1276 }
1277 return false;
1278 }
1279
1280 void set_tool_sprite(int tool, int type)
1281 {
1282 int spr = ZQM_NORMAL;
1283 switch(tool)
1284 {
1285 case t_pen: spr = ZQM_SWORD; break;
1286 case t_fill: spr = ZQM_POTION; break;
1287 case t_recolor: spr = ZQM_WAND; break;
1288 case t_eyedropper: spr = ZQM_LENS; break;
1289 case t_move: spr = ZQM_GLOVE_OPEN+type; break;
1290 case t_select: spr = ZQM_HOOK_PLAIN+type; break;
1291 case t_wand: spr = ZQM_SEL_WAND_PLAIN+type; break;
1292 }
1293 MouseSprite::set(spr);
1294 }
1295 void update_tool_cursor()
1296 {
1297 int32_t temp_mouse_x=gui_mouse_x();
1298 int32_t temp_mouse_y=gui_mouse_y();
1299
1300 int32_t type=0;
1301
1302 if(has_selection())
1303 {
1304 switch(tool)
1305 {
1306 case t_select:
1307 case t_wand:
1308 type+=select_mode;
1309 break;
1310 }
1311 }
1312
1313 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
1314 {
1315 if(tool_cur==-1)
1316 set_tool_sprite(tool,type);
1317
1318 tool_cur=tool;
1319 }
1320 else if(tool_cur != -1)
1321 {
1322 MouseSprite::set(ZQM_NORMAL);
1323 tool_cur = -1;
1324 }
1325 }
1326
1327 void draw_edit_scr(int32_t tile,int32_t flip,int32_t cs,byte *oldtile,bool create_tbar)
1328 {
1329 PALETTE tpal;
1330 static BITMAP *tbar = create_bitmap_ex(8,zq_screen_w-6, 18);
1331 static BITMAP *preview_bmp = create_bitmap_ex(8, 64, 64);
1332 jwin_draw_win(screen2, 0, 0, zq_screen_w, zq_screen_h, FR_WIN);
1333
1334 if(!create_tbar)
1335 {
1336 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1337 }
1338 else
1339 {
1340 jwin_draw_titlebar(tbar, 0, 0, zq_screen_w-6, 18, "", true, true);
1341 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1342 }
1343
1344 textprintf_ex(screen2,get_zc_font(font_lfont),5,5,jwin_pal[jcTITLEFG],-1,"Tile Editor (%d)",tile);
1345
1346 clear_to_color(preview_bmp, 0);
1347
1348 zc_swap(oldtile,newtilebuf[tile].data); //Put oldtile in the tile buffer
1349 jwin_draw_win(screen2, prev_til_1.x-2,prev_til_1.y-2, prev_til_1.w+4, prev_til_1.h+4, FR_DEEP);
1350 puttile16(preview_bmp,tile,0,0,cs,flip);
1351 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_1.x, prev_til_1.y, prev_til_1.w, prev_til_1.h);
1352
1353 clear_to_color(preview_bmp, 0);
1354 jwin_draw_win(screen2, prev_til_2.x-2,prev_til_2.y-2, prev_til_2.w+4, prev_til_2.h+4, FR_DEEP);
1355 overtile16(preview_bmp,tile,0,0,cs,flip);
1356 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_2.x, prev_til_2.y, prev_til_2.w, prev_til_2.h);
1357 zc_swap(oldtile,newtilebuf[tile].data); //Swap the real tile back to the buffer
1358
1359 unpack_tile(newtilebuf, tile, 0, true);
1360 if(floating_sel)
1361 for(auto q = 0; q < 256; ++q)
1362 if(floatsel[q])
1363 unpackbuf[q] = floatsel[q];
1364 byte tmptile[256];
1365 byte *tmpptr = tmptile;
1366 zc_swap(tmpptr,newtilebuf[tile].data); //Put temp data in the tile buffer
1367 pack_tile(newtilebuf,unpackbuf,tile);
1368 clear_to_color(preview_bmp, 0);
1369
1370 jwin_draw_win(screen2, prev_til_3.x-2,prev_til_3.y-2, prev_til_3.w+4, prev_til_3.h+4, FR_DEEP);
1371 puttile16(preview_bmp,tile,0,0,cs,flip);
1372 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_3.x, prev_til_3.y, prev_til_3.w, prev_til_3.h);
1373
1374 clear_to_color(preview_bmp, 0);
1375 jwin_draw_win(screen2, prev_til_4.x-2,prev_til_4.y-2, prev_til_4.w+4, prev_til_4.h+4, FR_DEEP);
1376 overtile16(preview_bmp,tile,0,0,cs,flip);
1377 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_4.x, prev_til_4.y, prev_til_4.w, prev_til_4.h);
1378
1379 if(reftile > 0)
1380 {
1381 clear_to_color(preview_bmp, 0);
1382 jwin_draw_win(screen2, ref_til.x-2,ref_til.y-2, ref_til.w+4, ref_til.h+4, FR_DEEP);
1383 overtile16(preview_bmp,reftile,0,0,cs,flip);
1384 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, ref_til.x, ref_til.y, ref_til.w, ref_til.h);
1385 }
1386
1387 //Color info
1388 {
1389 color_info.h = 1;
1390 if(showcolortip)
1391 {
1392 auto fh = color_info.yscale = text_height(font);
1393 int ty = color_info.y;
1394 if(reftile <= 0)
1395 ty -= ref_til.h + 8;
1396 int y = ty;
1397 int rx = color_info.x+color_info.xscale;
1398 gui_textout_ln(screen2,font,(unsigned char*)"Colors:",
1399 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1400 auto str = get_tile_colornames(tile,cs);
1401 size_t pos = 0;
1402 char buf[512] = {0};
1403 char cbuf[16] = {0};
1404 while(pos < str.size())
1405 {
1406 y += fh;
1407 if(y+fh > zq_screen_h)
1408 break; //Out of space!
1409 auto endpos = str.find_first_of('\n',pos);
1410
1411 if(endpos == std::string::npos)
1412 {
1413 strcpy(buf,str.substr(pos).c_str());
1414 pos = str.size();
1415 }
1416 else
1417 {
1418 strcpy(buf,str.substr(pos,endpos-pos+1).c_str());
1419 pos = endpos+1;
1420 }
1421 //Ensure the name fits horizontally
1422 if(text_length(font,buf) > color_info.xscale)
1423 {
1424 size_t pos = 0;
1425 for(; buf[pos]; ++pos)
1426 {
1427 if(buf[pos] == ':')
1428 {
1429 strcpy(cbuf, buf+pos);
1430 buf[pos] = 0;
1431 break;
1432 }
1433 }
1434 size_t clen = text_length(font,cbuf);
1435 size_t dotlen = text_length(font,"..");
1436
1437 while(pos > 0 && (dotlen+clen+text_length(font,buf) > color_info.xscale))
1438 buf[--pos] = 0;
1439 while(buf[pos] == ' ')
1440 buf[pos] = 0;
1441 strcat(buf,"..");
1442 strcat(buf,cbuf);
1443 }
1444 gui_textout_ln(screen2,font,(unsigned char const*)buf,
1445 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1446 ++color_info.h;
1447 }
1448 jwin_draw_frame(screen2,color_info.x-2,ty-2,(color_info.w*color_info.xscale)+4,(color_info.h*color_info.yscale)+4,FR_DEEP);
1449 }
1450 else
1451 {
1452 int ty = color_info_btn.y;
1453 if(reftile <= 0)
1454 ty -= ref_til.h + 8;
1455 draw_text_button(screen2,color_info_btn.x,ty,color_info_btn.w,color_info_btn.h,
1456 "Show Colors",vc(1),vc(14),0,true);
1457 }
1458 }
1459
1460 zc_swap(tmpptr,newtilebuf[tile].data); //Swap the real tile back to the buffer
1461
1462 jwin_draw_win(screen2, zoomtile.x-3, zoomtile.y-3, (zoomtile.w*zoomtile.xscale)+5, (zoomtile.h*zoomtile.yscale)+5, FR_DEEP);
1463 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
1464
1465 if(floating_sel)
1466 textprintf_ex(screen2,font,status_info.x,status_info.y+0,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Floating selection");
1467 textprintf_ex(screen2,font,status_info.x,status_info.y+(1*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile: %d",tile);
1468 if(newtilebuf[tile].format==tf8Bit)
1469 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"8-bit");
1470 else
1471 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cset: %d",cs);
1472
1473 PALETTE temppal;
1474
1475 //palette and mouse
1476 switch(newtilebuf[tile].format)
1477 {
1478 case tf4Bit:
1479 jwin_draw_win(screen2, cpalette_4.x-2, cpalette_4.y-2, (cpalette_4.xscale*cpalette_4.w)+4, (cpalette_4.yscale*cpalette_4.h)+4, FR_DEEP);
1480 get_palette(temppal);
1481
1482 for(int32_t i=0; i<cpalette_4.w*cpalette_4.h; i++)
1483 {
1484 size_and_pos const& s = cpalette_4.subsquare(i);
1485 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,CSET(cs)+i);
1486 }
1487
1488 little_x(screen2,cpalette_4.x+1,cpalette_4.y+1,invcol,cpalette_4.xscale-5,cpalette_4.yscale-5);
1489 break;
1490
1491 case tf8Bit:
1492 jwin_draw_win(screen2, cpalette_8.x-2, cpalette_8.y-2, (cpalette_8.xscale*cpalette_8.w)+4, (cpalette_8.yscale*cpalette_8.h)+4, FR_DEEP);
1493
1494 for(int32_t i=0; i<cpalette_8.w*cpalette_8.h; ++i)
1495 {
1496 size_and_pos const& s = cpalette_8.subsquare(i);
1497 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,i);
1498 }
1499
1500 little_x(screen2,cpalette_8.x+1,cpalette_8.y+1,invcol,cpalette_8.xscale-5,cpalette_8.yscale-5);
1501 break;
1502 }
1503
1504 rect(screen2, bg_prev.x, bg_prev.y, bg_prev.x+bg_prev.w-1, bg_prev.y+bg_prev.h-1, jwin_pal[jcTEXTFG]);
1505 rectfill(screen2, bg_prev.x+1, bg_prev.y+1, bg_prev.x+bg_prev.w-2, bg_prev.y+bg_prev.h-2, jwin_pal[jcTEXTBG]);
1506 rectfill(screen2, bg_prev.x+3, bg_prev.y+3, bg_prev.x+bg_prev.w-4, bg_prev.y+bg_prev.h-4, c2+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1507
1508 if(c2==0)
1509 {
1510 little_x(screen2, bg_prev.x+1, bg_prev.y+1, invcol, bg_prev.w-2, bg_prev.h-2);
1511 }
1512
1513 rect(screen2, fg_prev.x, fg_prev.y, fg_prev.x+fg_prev.w-1, fg_prev.y+fg_prev.h-1, jwin_pal[jcTEXTFG]);
1514 rectfill(screen2, fg_prev.x+1, fg_prev.y+1, fg_prev.x+fg_prev.w-2, fg_prev.y+fg_prev.h-2, jwin_pal[jcTEXTBG]);
1515 rectfill(screen2, fg_prev.x+3, fg_prev.y+3, fg_prev.x+fg_prev.w-4, fg_prev.y+fg_prev.h-4, c1+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1516
1517 if(c1==0)
1518 {
1519 little_x(screen2, fg_prev.x+1, fg_prev.y+1, invcol, fg_prev.w-2, fg_prev.h-2);
1520 }
1521
1522 draw_text_button(screen2,ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK",vc(1),vc(14),0,true);
1523 draw_text_button(screen2,cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel",vc(1),vc(14),0,true);
1524 draw_text_button(screen2,edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal",vc(1),vc(14),0,true);
1525 draw_checkbox(screen2,hlcbox.x, hlcbox.y, hlcbox.w, hlcbox.h, tthighlight);
1526 gui_textout_ln(screen2,font,(unsigned char*)"Highlight Hover",hlcbox.x+hlcbox.w+2,hlcbox.y+hlcbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1527
1528 draw_checkbox(screen2,quartgrid_cbox.x, quartgrid_cbox.y, quartgrid_cbox.w, quartgrid_cbox.h, show_quartgrid);
1529 gui_textout_ln(screen2,font,(unsigned char*)"Quarter Grid",quartgrid_cbox.x+quartgrid_cbox.w+2,quartgrid_cbox.y+quartgrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1530
1531 draw_checkbox(screen2,hidegrid_cbox.x, hidegrid_cbox.y, hidegrid_cbox.w, hidegrid_cbox.h, hide_grid);
1532 gui_textout_ln(screen2,font,(unsigned char*)"Hide Grid",hidegrid_cbox.x+hidegrid_cbox.w+2,hidegrid_cbox.y+hidegrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1533
1534 bool qgrd = show_quartgrid && qgrid_tool(tool);
1535 gui_textout_ln(screen2,font,(unsigned char*)"Quarter-Grid Draw Modes", reflbtn_grid.x, reflbtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],qgrd?0:D_DISABLED);
1536 for(int q = 0; q < REFL_MAX; ++q)
1537 {
1538 auto& sqr = reflbtn_grid.subsquare(q);
1539 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[q],vc(1),vc(14),qgrd ? ((refl_flags&(1<<q)) ? D_SELECTED : 0) : D_DISABLED,true);
1540 }
1541 gui_textout_ln(screen2,font,(unsigned char*)"Transparent Mode", xmodebtn_grid.x, xmodebtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1542 for(int q = 0; q < XMODE_MAX; ++q)
1543 {
1544 auto& sqr = xmodebtn_grid.subsquare(q);
1545 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[q],vc(1),vc(14),(xmode == q) ? D_SELECTED : 0,true);
1546 }
1547 for(int q = 0; q < BGMODE_MAX; ++q)
1548 {
1549 auto& sqr = bgmodebtn_grid.subsquare(q);
1550 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[q],vc(1),vc(14),(bgmode == q) ? D_SELECTED : 0,true);
1551 }
1552
1553 //tool buttons
1554 for(int32_t toolbtn = 0; toolbtn < t_max; ++toolbtn)
1555 {
1556 auto bmp = toolbtn+MOUSE_BMP_SWORD;
1557 int col = toolbtn%tool_btns.w;
1558 int row = toolbtn/tool_btns.w;
1559
1560 jwin_draw_button(screen2,tool_btns.x+(col*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale,tool==toolbtn?2:0,0);
1561 masked_stretch_blit(mouse_bmp_1x[bmp][0],screen2,0,0,16,16,tool_btns.x+(col*tool_btns.xscale)+3+(tool==toolbtn?1:0),tool_btns.y+3+(row*tool_btns.yscale)+(tool==toolbtn?1:0),tool_btns.xscale-7,tool_btns.yscale-7);
1562 }
1563
1564 //coordinates
1565 {
1566 auto mx = gui_mouse_x();
1567 auto my = gui_mouse_y();
1568 int32_t ind = zoomtile.rectind(mx,my);
1569 int32_t temp_x=ind%zoomtile.w;
1570 int32_t temp_y=ind/zoomtile.w;
1571 int color = -1;
1572
1573 bool is8b = newtilebuf[tile].format > tf4Bit;
1574 if(ind > -1)
1575 {
1576 char xbuf[16];
1577 sprintf(xbuf, "x: %d", temp_x);
1578 textprintf_ex(screen2,font,status_info.x,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%s",xbuf);
1579 textprintf_ex(screen2,font,status_info.x+text_length(font,xbuf)+8,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"y: %d",temp_y);
1580 unpack_tile(newtilebuf, tile, 0, false);
1581 byte *si = unpackbuf;
1582 si+=ind;
1583 color = *si;
1584 }
1585 else if(fg_prev.rect(mx,my))
1586 color = c1;
1587 else if(bg_prev.rect(mx,my))
1588 color = c2;
1589 else color = (is8b ? cpalette_8 : cpalette_4).rectind(mx,my);
1590 if(color > -1)
1591 {
1592 get_palette(tpal);
1593 char separator = ' ';
1594 char buf[512] = {0};
1595
1596 int realcol = color+(is8b?0:CSET(cs));
1597 bool xcolor = (is8b ? realcol == 0 : (realcol%16)==0);
1598 auto& c = tpal[realcol];
1599
1600 if(tthighlight)
1601 {
1602 size_and_pos const& mainsqr = is8b ? cpalette_8 : cpalette_4;
1603 size_and_pos const& csqr = mainsqr.subsquare(color);
1604
1605 int hlcol = getHighlightColor(tpal[realcol]);
1606 int hlthick = 4;
1607 int extraborder = is8b ? 8 : 0;
1608 int borderthick = hlthick+extraborder;
1609
1610 if(is8b)
1611 {
1612 highlight_sqr(screen2, 0xED, csqr.x, mainsqr.y, csqr.w, mainsqr.h*mainsqr.yscale, hlthick); //column
1613 highlight_sqr(screen2, 0xED, mainsqr.x, csqr.y, mainsqr.w*mainsqr.xscale, csqr.h, hlthick); //row
1614 }
1615 highlight_sqr(screen2, 0xED, csqr.x-borderthick, csqr.y-borderthick, csqr.w+borderthick*2, csqr.h+borderthick*2, hlthick); //square hl
1616 rectfill(screen2, csqr.x-extraborder, csqr.y-extraborder, csqr.x+csqr.w-1+extraborder, csqr.y+csqr.h-1+extraborder, realcol); //square color
1617 if(xcolor)
1618 little_x(screen2, csqr.x-extraborder+4, csqr.y-extraborder+4, invcol, csqr.w+(extraborder*2)-8, csqr.h+(extraborder*2)-8); //transparent X
1619 highlight_sqr(screen2, hlcol, csqr.x-extraborder, csqr.y-extraborder, csqr.w+extraborder*2, csqr.h+extraborder*2, 1); //highlight border
1620 }
1621
1622 sprintf(buf, "%02d %02d %02d %c(0x%02X %d)",c.r,c.g,c.b,separator,realcol,color);
1623 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(2*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1624
1625 strcpy(buf, get_color_name(realcol, is8b).c_str());
1626 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(1*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1627
1628 sprintf(buf, "#%02X%02X%02X", tpal[realcol].r,tpal[realcol].g,tpal[realcol].b);
1629 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(0),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1630
1631 rect(screen2, hov_prev.x, hov_prev.y, hov_prev.x+hov_prev.w-1, hov_prev.y+hov_prev.h-1, jwin_pal[jcTEXTFG]);
1632 rectfill(screen2, hov_prev.x+1, hov_prev.y+1, hov_prev.x+hov_prev.w-2, hov_prev.y+hov_prev.h-2, jwin_pal[jcTEXTBG]);
1633 rectfill(screen2, hov_prev.x+3, hov_prev.y+3, hov_prev.x+hov_prev.w-4, hov_prev.y+hov_prev.h-4, realcol);
1634 if(xcolor)
1635 little_x(screen2, hov_prev.x+1, hov_prev.y+1, invcol, hov_prev.w-2, hov_prev.h-2);
1636 }
1637 }
1638
1639 custom_vsync();
1640 blit(screen2,screen,0,0,0,0,zq_screen_w,zq_screen_w);
1641 update_tool_cursor();
1642 SCRFIX();
1643 }
1644
1645 void normalize(int32_t tile,int32_t tile2, bool rect_sel, int32_t flip)
1646 {
1647 unfloat_selection();
1648 if(tile>tile2)
1649 {
1650 zc_swap(tile, tile2);
1651 }
1652
1653 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
1654 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
1655
1656 int32_t start=tile;
1657 int32_t end=tile2;
1658
1659 // Might have top-right and bottom-left corners selected...
1660 if(rect_sel && TILECOL(tile)>TILECOL(tile2))
1661 {
1662 start=tile-(TILECOL(tile)-TILECOL(tile2));
1663 end=tile2+(TILECOL(tile)-TILECOL(tile2));
1664 }
1665
1666 for(int32_t temptile=start; temptile<=end; temptile++)
1667 {
1668 if(!rect_sel || ((TILECOL(temptile)>=left) && (TILECOL(temptile)<=left+columns-1)))
1669 {
1670 unpack_tile(newtilebuf, temptile, 0, true);
1671
1672 if(flip&1)
1673 {
1674 for(int32_t y=0; y<16; y++)
1675 {
1676 for(int32_t x=0; x<8; x++)
1677 {
1678 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[(y<<4)+15-x]);
1679 }
1680 }
1681 }
1682
1683 if(flip&2)
1684 {
1685 for(int32_t y=0; y<8; y++)
1686 {
1687 for(int32_t x=0; x<16; x++)
1688 {
1689 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[((15-y)<<4)+x]);
1690 }
1691 }
1692 }
1693
1694 pack_tile(newtilebuf,unpackbuf,temptile);
1695 }
1696 }
1697 }
1698
1699 void rotate_tile(int32_t tile, bool backward)
1700 {
1701 unfloat_selection();
1702 unpack_tile(newtilebuf, tile, 0, true);
1703 byte tempunpackbuf[256];
1704 byte tempx, tempy;
1705
1706 for(tempx=0; tempx<16; tempx++)
1707 {
1708 for(tempy=0; tempy<16; tempy++)
1709 {
1710 if(!backward)
1711 {
1712 tempunpackbuf[(tempy<<4)+tempx]=unpackbuf[((15-tempx)<<4)+tempy];
1713 }
1714 else
1715 {
1716 tempunpackbuf[((15-tempx)<<4)+tempy]=unpackbuf[(tempy<<4)+tempx];
1717 }
1718 }
1719 }
1720
1721 pack_tile(newtilebuf,tempunpackbuf,tile);
1722 }
1723
1724 static int32_t undocount=128;
1725 byte undotile[256];
1726
1727 void wrap_tile(int32_t tile, int32_t vertical, int32_t horizontal, bool clear)
1728 {
1729 byte buf[256];
1730
1731 for(int32_t i=0; i<undocount; i++)
1732 {
1733 newtilebuf[tile].data[i]=undotile[i];
1734 }
1735
1736 if(!(horizontal||vertical))
1737 {
1738 return;
1739 }
1740
1741 unpack_tile(newtilebuf, tile, 0, true);
1742
1743 for(int32_t i=0; i<256; i++)
1744 {
1745 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1746 buf[shift_ind] = unpackbuf[i];
1747 }
1748
1749 if(clear)
1750 {
1751 for(int32_t r=0; r<abs(vertical); r++)
1752 {
1753 for(int32_t c=0; c<16; c++)
1754 {
1755 buf[(vertical>0?r:15-r)*16+c]=0;
1756 }
1757 }
1758
1759 for(int32_t r=0; r<16; r++)
1760 {
1761 for(int32_t c=0; c<abs(horizontal); c++)
1762 {
1763 buf[r*16+(horizontal>0?c:15-c)]=0;
1764 }
1765 }
1766 }
1767
1768 pack_tile(newtilebuf,buf,tile);
1769 }
1770
1771 void wrap_sel_tile(int32_t vertical, int32_t horizontal)
1772 {
1773 byte buf[256];
1774
1775 if(!(horizontal||vertical))
1776 {
1777 return;
1778 }
1779
1780 memset(buf,0,256);
1781
1782 for(int32_t i=0; i<256; i++)
1783 {
1784 if(is_in_selection(i%16,i/16))
1785 {
1786 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1787 buf[shift_ind] = floatsel[i];
1788 }
1789 }
1790
1791 memcpy(floatsel,buf,256);
1792 }
1793
1794 void float_selection(int32_t tile, bool clear)
1795 {
1796 if(floating_sel) return;
1797 floating_sel = true;
1798 floating_tile = tile;
1799
1800 unpack_tile(newtilebuf, tile, 0, true);
1801
1802 for(auto q = 0; q < 256; ++q)
1803 {
1804 if(is_in_selection(q%16,q/16))
1805 {
1806 floatsel[q] = unpackbuf[q];
1807 unpackbuf[q] = clear ? 0 : c2;
1808 }
1809 else floatsel[q] = 0;
1810 }
1811
1812 pack_tile(newtilebuf,unpackbuf,tile);
1813 }
1814
1815 void unfloat_selection()
1816 {
1817 if(!floating_sel) return;
1818 floating_sel = false;
1819
1820 unpack_tile(newtilebuf, floating_tile, 0, true);
1821
1822 for(auto q = 0; q < 256; ++q)
1823 {
1824 if(floatsel[q])
1825 {
1826 unpackbuf[q] = floatsel[q];
1827 }
1828 }
1829
1830 pack_tile(newtilebuf,unpackbuf,floating_tile);
1831 floating_tile = -1;
1832 }
1833
1834 void shift_tile_colors(int32_t tile, int32_t amount, bool ignore_transparent)
1835 {
1836 if(floating_sel)
1837 {
1838 for(auto q = 0; q < 256; ++q)
1839 {
1840 if(ignore_transparent && floatsel[q]==0)
1841 continue;
1842 floatsel[q]=wrap(floatsel[q]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1843 }
1844 return;
1845 }
1846
1847 byte buf[256];
1848 unpack_tile(newtilebuf, tile, 0, true);
1849
1850 for(int32_t i=0; i<256; i++)
1851 {
1852 buf[i]=unpackbuf[i];
1853
1854 if(!is_in_selection(i&0x0F, (i&0xF0)>>4))
1855 continue;
1856
1857 if(ignore_transparent)
1858 {
1859 if(buf[i]==0)
1860 continue;
1861
1862 buf[i]=wrap(buf[i]+amount, 1, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1863 }
1864 else // Don't ignore transparent
1865 buf[i]=wrap(buf[i]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1866 }
1867
1868 pack_tile(newtilebuf,buf,tile);
1869 }
1870
1871 void clear_selection_grid()
1872 {
1873 unfloat_selection();
1874 for(int32_t x=0; x<18; ++x)
1875 {
1876 for(int32_t y=0; y<18; ++y)
1877 {
1878 selection_grid[x][y]=0;
1879 }
1880 }
1881 }
1882
1883 void invert_selection_grid()
1884 {
1885 unfloat_selection();
1886 for(int32_t x=1; x<17; ++x)
1887 {
1888 for(int32_t y=1; y<17; ++y)
1889 {
1890 selection_grid[x][y]=selection_grid[x][y]?0:1;
1891 }
1892 }
1893 }
1894
1895 void shift_selection_grid(int32_t xoffs, int32_t yoffs)
1896 {
1897 byte local_grid[16][16];
1898 memset(local_grid, 0, sizeof(local_grid));
1899 for(auto x = 0; x < 16; ++x)
1900 {
1901 for(auto y = 0; y < 16; ++y)
1902 {
1903 auto offs_x = (x+xoffs)%16, offs_y = (y+yoffs)%16;
1904 if(offs_x < 0) offs_x = (16 - abs(offs_x));
1905 if(offs_y < 0) offs_y = (16 - abs(offs_y));
1906 local_grid[offs_x][offs_y] = selection_grid[x+1][y+1]?1:0;
1907 }
1908 }
1909 for(auto x = 0; x < 16; ++x)
1910 {
1911 for(auto y = 0; y < 16; ++y)
1912 {
1913 selection_grid[x+1][y+1] = local_grid[x][y]?1:0;
1914 }
1915 }
1916 }
1917
1918 void show_edit_tile_help()
1919 {
1920 InfoDialog("Help: Tile Editor", "Hotkeys:"
1921 "\nF1: This Help Dialog"
1922 "\nEnter: Unfloat Sel / OK | Esc: Unfloat Sel / Cancel"
1923 "\nDelete: Clear Tile/Sel | Ctrl+Delete: Clear Tile"
1924 "\nA: Sel All | D: Unselect Sel | I: Invert Sel"
1925 "\nH/V: Flip | (Shift+)R: Rotate"
1926 "\n+/-: Change CSet | Ctrl +/-: Shift Colors"
1927 "\n(Ctrl+)S: Swap Colors | U/Ctrl+Z: Undo"
1928 "\nF12: Screenshot (whole screen)"
1929 "\nArrows: Shift Pixel | Ctrl+Arrows: Change Tile"
1930 "\nWhen not on Select tools, hold to swap:"
1931 "\nCtrl - Fill | Alt - Grab | Ctrl+Alt - Recolor").show();
1932 }
1933
1934 static int move_origin_x=-1, move_origin_y=-1;
1935 static int prev_x=-1, prev_y=-1;
1936 bool __pixel_draw(int x, int y, int tile, int flip)
1937 {
1938 bool ret = false;
1939 switch(tool)
1940 {
1941 case t_pen:
1942 if(flip&1) x=15-x;
1943
1944 if(flip&2) y=15-y;
1945
1946 if(is_in_selection(x,y))
1947 {
1948 if(floating_sel)
1949 {
1950 floatsel[(y<<4)+x]=(drawing==1)?c1:c2;
1951 }
1952 else
1953 {
1954 unpack_tile(newtilebuf, tile, 0, false);
1955 unpackbuf[((y<<4)+x)]=(drawing==1)?c1:c2;
1956 pack_tile(newtilebuf, unpackbuf,tile);
1957 }
1958 }
1959 break;
1960
1961 case t_fill:
1962 if(is_in_selection(x,y))
1963 {
1964 tile_floodfill(tile,x,y,(drawing==1)?c1:c2);
1965 ret = true;
1966 }
1967 break;
1968
1969 case t_recolor:
1970 if(is_in_selection(x,y))
1971 {
1972 if(floating_sel)
1973 {
1974 tf_u = floatsel[(y<<4)+x];
1975 for(int32_t i=0; i<256; i++)
1976 {
1977 if(is_in_selection(i&15,i>>4))
1978 {
1979 if(floatsel[i]==tf_u)
1980 {
1981 floatsel[i]=(drawing==1)?c1:c2;
1982 }
1983 }
1984 }
1985 }
1986 else
1987 {
1988 unpack_tile(newtilebuf, tile, 0, false);
1989 tf_u = unpackbuf[(y<<4)+x];
1990 if(tf_u != ((drawing==1)?c1:c2))
1991 {
1992 for(int32_t i=0; i<256; i++)
1993 {
1994 if(is_in_selection(i&15,i>>4))
1995 {
1996 if(unpackbuf[i]==tf_u)
1997 {
1998 unpackbuf[i]=(drawing==1)?c1:c2;
1999 }
2000 }
2001 }
2002
2003 pack_tile(newtilebuf, unpackbuf,tile);
2004 }
2005 }
2006 ret = true;
2007 }
2008 break;
2009
2010 case t_eyedropper:
2011 if(floating_sel)
2012 memcpy(unpackbuf, floatsel, 256);
2013 else unpack_tile(newtilebuf, tile, 0, false);
2014
2015 if(gui_mouse_b()&1)
2016 {
2017 c1=unpackbuf[((y<<4)+x)];
2018 }
2019
2020 if(gui_mouse_b()&2)
2021 {
2022 c2=unpackbuf[((y<<4)+x)];
2023 }
2024 break;
2025
2026 case t_move:
2027 if((prev_x!=x)||(prev_y!=y))
2028 {
2029 if(has_selection())
2030 {
2031 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2032 wrap_sel_tile(y-prev_y, x-prev_x);
2033 shift_selection_grid(x-prev_x, y-prev_y);
2034 }
2035 else wrap_tile(tile, y-move_origin_y, x-move_origin_x, drawing==2);
2036 prev_x=x;
2037 prev_y=y;
2038 }
2039 break;
2040
2041 case t_select:
2042 unfloat_selection();
2043 if(flip&1) x=15-x;
2044
2045 if(flip&2) y=15-y;
2046
2047 if(selecting_x1==-1||selecting_y1==-1)
2048 {
2049 selecting_x1=x;
2050 selecting_y1=y;
2051 }
2052 else
2053 {
2054 selecting_x2=x;
2055 selecting_y2=y;
2056 }
2057 break;
2058
2059 case t_wand:
2060 unfloat_selection();
2061 if(flip&1) x=15-x;
2062
2063 if(flip&2) y=15-y;
2064
2065 switch(select_mode)
2066 {
2067 case 0:
2068 clear_selection_grid();
2069 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2070 break;
2071
2072 case 1:
2073 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2074 break;
2075
2076 case 2:
2077 remove_color_from_selection(unpackbuf[((y<<4)+x)]);
2078 break;
2079
2080 case 3:
2081 intersect_color_with_selection(unpackbuf[((y<<4)+x)]);
2082 break;
2083 }
2084
2085 ret = true;
2086 break;
2087 }
2088 return ret;
2089 }
2090 void edit_tile(int32_t tile,int32_t flip,int32_t &cs)
2091 {
2092 popup_zqdialog_start();
2093 FONT* oldfont = font;
2094 font = get_custom_font(CFONT_DLG);
2095 edit_button.h = ok_button.h = cancel_button.h = 12+text_height(font);
2096 status_info.yscale = text_height(font);
2097 status_info.y = 308-(status_info.h*status_info.yscale);
2098 hover_info.yscale = status_info.yscale;
2099 hover_info.y = 338-(hover_info.h*hover_info.yscale);
2100 go();
2101 undocount = tilesize(newtilebuf[tile].format);
2102 clear_selection_grid();
2103 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2104
2105 tthighlight = zc_get_config("ZQ_GUI","tile_edit_fancyhighlight",1);
2106 showcolortip = zc_get_config("ZQ_GUI","tile_edit_colornames",1);
2107
2108 PALETTE tpal;
2109 byte oldtile[256];
2110
2111 memset(&tpal, 0, sizeof(PALETTE));
2112 memset(oldtile, 0, 256);
2113
2114 for(int32_t i=0; i<undocount; i++)
2115 {
2116 oldtile[i]=undotile[i]=newtilebuf[tile].data[i];
2117 }
2118 byte undoselgrid[16][16];
2119 for(auto x = 0; x < 16; ++x)
2120 for(auto y = 0; y < 16; ++y)
2121 undoselgrid[x][y] = selection_grid[x+1][y+1];
2122 for(auto q = 0; q < 256; ++q)
2123 {
2124 floatsel[q] = 0;
2125 undofloatsel[q] = 0;
2126 floating_sel = false;
2127 undo_is_floatsel = false;
2128 }
2129
2130 int32_t tile_x=-1, tile_y=-1;
2131 int32_t temp_x=-1, temp_y=-1;
2132 bool bdown=false;
2133 int32_t done=0;
2134 drawing=0;
2135 tool_cur = -1;
2136
2137 get_palette(tpal);
2138
2139 if(newtilebuf[tile].format==tf4Bit)
2140 {
2141 invcol=makecol8(255 - tpal[CSET(cs)].r, 255 - tpal[CSET(cs)].g, 255 - tpal[CSET(cs)].b);
2142 }
2143 else
2144 {
2145 invcol=makecol8(255 - tpal[0].r, 255 - tpal[0].g, 255 - tpal[0].b);
2146 }
2147
2148 custom_vsync();
2149 zc_set_palette(tpal);
2150 draw_edit_scr(tile,flip,cs,oldtile, true);
2151
2152 while(gui_mouse_b())
2153 {
2154 /* do nothing */
2155 rest(1);
2156 }
2157
2158 move_origin_x=-1;
2159 move_origin_y=-1;
2160 prev_x=-1;
2161 prev_y=-1;
2162
2163
2164
2165 byte selection_pattern_source[8][8]=
2166 {
2167 {1, 1, 1, 1, 0, 0, 0, 0},
2168 {1, 1, 1, 0, 0, 0, 0, 1},
2169 {1, 1, 0, 0, 0, 0, 1, 1},
2170 {1, 0, 0, 0, 0, 1, 1, 1},
2171 {0, 0, 0, 0, 1, 1, 1, 1},
2172 {0, 0, 0, 1, 1, 1, 1, 0},
2173 {0, 0, 1, 1, 1, 1, 0, 0},
2174 {0, 1, 1, 1, 1, 0, 0, 0},
2175 };
2176
2177 byte selecting_pattern_source[8][8]=
2178 {
2179 {1, 1, 0, 0, 0, 0, 1, 1},
2180 {1, 0, 0, 0, 0, 1, 1, 1},
2181 {0, 0, 0, 0, 1, 1, 1, 1},
2182 {0, 0, 0, 1, 1, 1, 1, 0},
2183 {0, 0, 1, 1, 1, 1, 0, 0},
2184 {0, 1, 1, 1, 1, 0, 0, 0},
2185 {1, 1, 1, 1, 0, 0, 0, 0},
2186 {1, 1, 1, 0, 0, 0, 0, 1},
2187 };
2188
2189 byte intersection_pattern_source[8][8]=
2190 {
2191 {0, 0, 1, 1, 0, 0, 1, 1},
2192 {0, 1, 1, 0, 0, 1, 1, 0},
2193 {1, 1, 0, 0, 1, 1, 0, 0},
2194 {1, 0, 0, 1, 1, 0, 0, 1},
2195 {0, 0, 1, 1, 0, 0, 1, 1},
2196 {0, 1, 1, 0, 0, 1, 1, 0},
2197 {1, 1, 0, 0, 1, 1, 0, 0},
2198 {1, 0, 0, 1, 1, 0, 0, 1},
2199 };
2200
2201 selection_pattern=create_bitmap_ex(8, 8, 8);
2202
2203 for(int32_t x=0; x<8; ++x)
2204 {
2205 for(int32_t y=0; y<8; ++y)
2206 {
2207 selection_pattern->line[y][x]=selection_pattern_source[x][y]?vc(0):vc(15);
2208 }
2209 }
2210
2211 selecting_pattern=create_bitmap_ex(8, 8, 8);
2212
2213 for(int32_t x=0; x<8; ++x)
2214 {
2215 for(int32_t y=0; y<8; ++y)
2216 {
2217 selecting_pattern->line[y][x]=selecting_pattern_source[x][y]?vc(0):vc(15);
2218 }
2219 }
2220
2221 intersection_pattern=create_bitmap_ex(8, 8, 8);
2222
2223 for(int32_t x=0; x<8; ++x)
2224 {
2225 for(int32_t y=0; y<8; ++y)
2226 {
2227 intersection_pattern->line[y][x]=intersection_pattern_source[x][y]?vc(0):vc(15);
2228 }
2229 }
2230
2231 do
2232 {
2233 HANDLE_CLOSE_ZQDLG();
2234 if(exiting_program) break;
2235 int32_t temp_mouse_x=gui_mouse_x();
2236 int32_t temp_mouse_y=gui_mouse_y();
2237 rest(4);
2238 bool redraw=false;
2239 bool did_wand_select=false;
2240
2241 if(keypressed())
2242 {
2243 bool ctrl = CHECK_CTRL_CMD;
2244 int k = readkey()>>8;
2245 switch(k)
2246 {
2247 case KEY_F1:
2248 show_edit_tile_help();
2249 break;
2250 case KEY_ENTER_PAD:
2251 case KEY_ENTER:
2252 if(floating_sel)
2253 unfloat_selection();
2254 else done=2;
2255 break;
2256
2257 case KEY_ESC:
2258 if(floating_sel)
2259 unfloat_selection();
2260 else if(has_selection())
2261 clear_selection_grid();
2262 else done=1;
2263 break;
2264
2265 case KEY_DEL:
2266 {
2267 unpack_tile(newtilebuf, tile, 0, false);
2268 bool all = CHECK_CTRL_CMD || !has_selection();
2269 bool canDel = false;
2270 if(all)
2271 {
2272 //Check all
2273 for(auto q = 0; q < 256; ++q)
2274 if(unpackbuf[q])
2275 {
2276 canDel = true;
2277 break;
2278 }
2279 }
2280 else
2281 {
2282 //Check selection
2283 for(auto x = 0; x < 16; ++x)
2284 for(auto y = 0; y < 16; ++y)
2285 if(is_in_selection(x,y))
2286 if(unpackbuf[(y<<4)+x])
2287 {
2288 canDel = true;
2289 break;
2290 }
2291 }
2292 if(!canDel) break; //don't delete (and thus reset undo) if nothing would change!
2293
2294 for(int32_t i=0; i<undocount; i++)
2295 {
2296 undotile[i]=newtilebuf[tile].data[i];
2297 }
2298 for(auto x = 0; x < 16; ++x)
2299 for(auto y = 0; y < 16; ++y)
2300 undoselgrid[x][y] = selection_grid[x+1][y+1];
2301 for(auto q = 0; q < 256; ++q)
2302 undofloatsel[q] = floatsel[q];
2303 undo_is_floatsel = floating_sel;
2304
2305 if(CHECK_CTRL_CMD || !has_selection())
2306 {
2307 //Delete all
2308 for(auto q = 0; q < 256; ++q)
2309 {
2310 unpackbuf[q] = 0;
2311 floatsel[q] = 0;
2312 }
2313 }
2314 else
2315 {
2316 //Delete selection
2317 for(auto x = 0; x < 16; ++x)
2318 for(auto y = 0; y < 16; ++y)
2319 {
2320 if(floating_sel)
2321 {
2322 floatsel[x+(y<<4)] = 0;
2323 }
2324 else if(is_in_selection(x,y))
2325 {
2326 unpackbuf[(y<<4)+x] = 0;
2327 }
2328 }
2329 }
2330 pack_tile(newtilebuf, unpackbuf, tile);
2331 redraw=true;
2332 }
2333 break;
2334
2335 case KEY_A:
2336 clear_selection_grid();
2337 invert_selection_grid();
2338 redraw=true;
2339 break;
2340
2341 case KEY_D:
2342 clear_selection_grid();
2343 redraw=true;
2344 break;
2345
2346 case KEY_I:
2347 invert_selection_grid();
2348 redraw=true;
2349 break;
2350
2351 case KEY_H:
2352 flip^=1;
2353 normalize(tile,tile,0,flip);
2354 flip=0;
2355 redraw=true;
2356 break;
2357
2358 case KEY_V:
2359 flip^=2;
2360 normalize(tile,tile,0,flip);
2361 flip=0;
2362 redraw=true;
2363 break;
2364
2365 case KEY_F12:
2366 onSnapshot();
2367 break;
2368
2369 case KEY_R:
2370 {
2371 //if(CHECK_CTRL_CMD))
2372 // {
2373 //do_recolor(tile); redraw=true; saved=false;
2374 // }
2375 //else
2376 // {
2377 go_tiles();
2378 rotate_tile(tile,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
2379 redraw=true;
2380 saved=false;
2381 break;
2382 }
2383
2384 case KEY_EQUALS:
2385 case KEY_PLUS_PAD:
2386 {
2387 if(CHECK_CTRL_CMD ||
2388 key[KEY_ALT] || key[KEY_ALTGR])
2389 {
2390 for(int32_t i=0; i<undocount; i++)
2391 undotile[i]=newtilebuf[tile].data[i];
2392 for(auto x = 0; x < 16; ++x)
2393 for(auto y = 0; y < 16; ++y)
2394 undoselgrid[x][y] = selection_grid[x+1][y+1];
2395 for(auto q = 0; q < 256; ++q)
2396 undofloatsel[q] = floatsel[q];
2397 undo_is_floatsel = floating_sel;
2398
2399 if(key[KEY_ALT] || key[KEY_ALTGR])
2400 shift_tile_colors(tile, 16, false);
2401 else
2402 shift_tile_colors(tile, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2403 }
2404 else
2405 cs = (cs<13) ? cs+1:0;
2406
2407 redraw=true;
2408 break;
2409 }
2410
2411 case KEY_MINUS:
2412 case KEY_MINUS_PAD:
2413 {
2414 if(CHECK_CTRL_CMD ||
2415 key[KEY_ALT] || key[KEY_ALTGR])
2416 {
2417 for(int32_t i=0; i<undocount; i++)
2418 undotile[i]=newtilebuf[tile].data[i];
2419 for(auto x = 0; x < 16; ++x)
2420 for(auto y = 0; y < 16; ++y)
2421 undoselgrid[x][y] = selection_grid[x+1][y+1];
2422 for(auto q = 0; q < 256; ++q)
2423 undofloatsel[q] = floatsel[q];
2424 undo_is_floatsel = floating_sel;
2425
2426 if(key[KEY_ALT] || key[KEY_ALTGR])
2427 shift_tile_colors(tile, -16, false);
2428 else
2429 shift_tile_colors(tile, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2430 }
2431 else
2432 cs = (cs>0) ? cs-1:13;
2433
2434 redraw=true;
2435 break;
2436 }
2437
2438 case KEY_SPACE:
2439 gridmode=(gridmode+1)%gm_max;
2440 redraw=true;
2441 break;
2442
2443 case KEY_Z:
2444 if(!ctrl)
2445 break;
2446 //Ctrl+Z == undo
2447 [[fallthrough]];
2448 case KEY_U:
2449 for(int32_t i=0; i<undocount; i++)
2450 zc_swap(undotile[i],newtilebuf[tile].data[i]);
2451
2452 for(auto x = 0; x < 16; ++x)
2453 for(auto y = 0; y < 16; ++y)
2454 zc_swap(selection_grid[x+1][y+1], undoselgrid[x][y]);
2455
2456 for(auto q = 0; q < 256; ++q)
2457 zc_swap(undofloatsel[q], floatsel[q]);
2458 zc_swap(undo_is_floatsel, floating_sel);
2459
2460 redraw=true;
2461 break;
2462
2463 case KEY_S:
2464 if(CHECK_CTRL_CMD)
2465 {
2466 for(int32_t i=0; i<undocount; i++)
2467 {
2468 undotile[i]=newtilebuf[tile].data[i];
2469 }
2470 for(auto x = 0; x < 16; ++x)
2471 for(auto y = 0; y < 16; ++y)
2472 undoselgrid[x][y] = selection_grid[x+1][y+1];
2473 for(auto q = 0; q < 256; ++q)
2474 undofloatsel[q] = floatsel[q];
2475 undo_is_floatsel = floating_sel;
2476
2477 unpack_tile(newtilebuf, tile, 0, false);
2478
2479 if(has_selection())
2480 {
2481 for(int32_t i=0; i<256; i++)
2482 {
2483 if(!is_in_selection(i%16,i/16))
2484 continue;
2485 if(unpackbuf[i]==c1)
2486 {
2487 unpackbuf[i]=c2;
2488 }
2489 else if(unpackbuf[i]==c2)
2490 {
2491 unpackbuf[i]=c1;
2492 }
2493 if(floating_sel)
2494 {
2495 if(floatsel[i]==c1)
2496 {
2497 floatsel[i]=c2;
2498 }
2499 else if(floatsel[i]==c2)
2500 {
2501 floatsel[i]=c1;
2502 }
2503 }
2504 }
2505 }
2506 else
2507 {
2508 for(int32_t i=0; i<256; i++)
2509 {
2510 if(unpackbuf[i]==c1)
2511 {
2512 unpackbuf[i]=c2;
2513 }
2514 else if(unpackbuf[i]==c2)
2515 {
2516 unpackbuf[i]=c1;
2517 }
2518 }
2519 }
2520
2521 pack_tile(newtilebuf, unpackbuf,tile);
2522 }
2523
2524 zc_swap(c1,c2);
2525 redraw=true;
2526 break;
2527
2528 case KEY_UP:
2529 if(CHECK_CTRL_CMD)
2530 {
2531 unfloat_selection();
2532 tile=zc_max(0,tile-TILES_PER_ROW);
2533 undocount = tilesize(newtilebuf[tile].format);
2534
2535 for(int32_t i=0; i<undocount; i++)
2536 {
2537 undotile[i]=newtilebuf[tile].data[i];
2538 oldtile[i]=undotile[i];
2539 }
2540
2541 redraw=true;
2542 }
2543 else
2544 {
2545 for(int32_t i=0; i<undocount; i++)
2546 {
2547 undotile[i]=newtilebuf[tile].data[i];
2548 }
2549 for(auto x = 0; x < 16; ++x)
2550 for(auto y = 0; y < 16; ++y)
2551 undoselgrid[x][y] = selection_grid[x+1][y+1];
2552 for(auto q = 0; q < 256; ++q)
2553 undofloatsel[q] = floatsel[q];
2554 undo_is_floatsel = floating_sel;
2555 if(has_selection())
2556 {
2557 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2558 wrap_sel_tile(-1, 0);
2559 shift_selection_grid(0, -1);
2560 }
2561 else wrap_tile(tile, -1, 0, false);
2562 redraw=true;
2563 }
2564 break;
2565
2566 case KEY_DOWN:
2567 if(CHECK_CTRL_CMD)
2568 {
2569 unfloat_selection();
2570 tile=zc_min(tile+TILES_PER_ROW,NEWMAXTILES-1);
2571 undocount = tilesize(newtilebuf[tile].format);
2572
2573 for(int32_t i=0; i<undocount; i++)
2574 {
2575 undotile[i]=newtilebuf[tile].data[i];
2576 oldtile[i]=undotile[i];
2577 }
2578
2579 redraw=true;
2580 }
2581 else
2582 {
2583 for(int32_t i=0; i<undocount; i++)
2584 {
2585 undotile[i]=newtilebuf[tile].data[i];
2586 }
2587 for(auto x = 0; x < 16; ++x)
2588 for(auto y = 0; y < 16; ++y)
2589 undoselgrid[x][y] = selection_grid[x+1][y+1];
2590 for(auto q = 0; q < 256; ++q)
2591 undofloatsel[q] = floatsel[q];
2592 undo_is_floatsel = floating_sel;
2593 if(has_selection())
2594 {
2595 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2596 wrap_sel_tile(1, 0);
2597 shift_selection_grid(0, 1);
2598 }
2599 else wrap_tile(tile, 1, 0, false);
2600 redraw=true;
2601 }
2602 break;
2603
2604 case KEY_LEFT:
2605 if(CHECK_CTRL_CMD)
2606 {
2607 unfloat_selection();
2608 tile=zc_max(0,tile-1);
2609 undocount = tilesize(newtilebuf[tile].format);
2610
2611 for(int32_t i=0; i<undocount; i++)
2612 {
2613 undotile[i]=newtilebuf[tile].data[i];
2614 oldtile[i]=undotile[i];
2615 }
2616
2617 redraw=true;
2618 }
2619 else
2620 {
2621 for(int32_t i=0; i<undocount; i++)
2622 {
2623 undotile[i]=newtilebuf[tile].data[i];
2624 }
2625 for(auto x = 0; x < 16; ++x)
2626 for(auto y = 0; y < 16; ++y)
2627 undoselgrid[x][y] = selection_grid[x+1][y+1];
2628 for(auto q = 0; q < 256; ++q)
2629 undofloatsel[q] = floatsel[q];
2630 undo_is_floatsel = floating_sel;
2631 if(has_selection())
2632 {
2633 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2634 wrap_sel_tile(0, -1);
2635 shift_selection_grid(-1, 0);
2636 }
2637 else wrap_tile(tile, 0, -1, false);
2638 redraw=true;
2639 }
2640 break;
2641
2642 case KEY_RIGHT:
2643 if(CHECK_CTRL_CMD)
2644 {
2645 unfloat_selection();
2646 tile=zc_min(tile+1, NEWMAXTILES-1);
2647 undocount = tilesize(newtilebuf[tile].format);
2648
2649 for(int32_t i=0; i<undocount; i++)
2650 {
2651 undotile[i]=newtilebuf[tile].data[i];
2652 oldtile[i]=undotile[i];
2653 }
2654
2655 redraw=true;
2656 }
2657 else
2658 {
2659 for(int32_t i=0; i<undocount; i++)
2660 {
2661 undotile[i]=newtilebuf[tile].data[i];
2662 }
2663 for(auto x = 0; x < 16; ++x)
2664 for(auto y = 0; y < 16; ++y)
2665 undoselgrid[x][y] = selection_grid[x+1][y+1];
2666 for(auto q = 0; q < 256; ++q)
2667 undofloatsel[q] = floatsel[q];
2668 undo_is_floatsel = floating_sel;
2669 if(has_selection())
2670 {
2671 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2672 wrap_sel_tile(0, 1);
2673 shift_selection_grid(1, 0);
2674 }
2675 else wrap_tile(tile, 0, 1, false);
2676 redraw=true;
2677 }
2678 break;
2679 case KEY_0: case KEY_1: case KEY_2: case KEY_3:
2680 case KEY_4: case KEY_5: case KEY_6: case KEY_7:
2681 case KEY_8: case KEY_9:
2682 case KEY_0_PAD: case KEY_1_PAD: case KEY_2_PAD: case KEY_3_PAD:
2683 case KEY_4_PAD: case KEY_5_PAD: case KEY_6_PAD: case KEY_7_PAD:
2684 case KEY_8_PAD: case KEY_9_PAD:
2685 {
2686 int t = k - ((k>KEY_9) ? KEY_1_PAD : KEY_1);
2687 if(unsigned(t) < t_max)
2688 {
2689 if(old_tool != -1)
2690 old_tool = t;
2691 else tool = t;
2692 }
2693 break;
2694 }
2695 case KEY_TAB:
2696 {
2697 if(key_shifts & KB_CTRL_CMD_FLAG)
2698 {
2699 xmode = (xmode+1)%XMODE_MAX;
2700 if(!xmode)
2701 bgmode = (bgmode+1)%BGMODE_MAX;
2702 }
2703 else if(key_shifts & KB_SHIFT_FLAG)
2704 hide_grid = !hide_grid;
2705 else show_quartgrid = !show_quartgrid;
2706 redraw = true;
2707 break;
2708 }
2709 }
2710 clear_keybuf();
2711 }
2712
2713 if(!gui_mouse_b())
2714 {
2715 if(is_selecting())
2716 {
2717 unfloat_selection();
2718 int32_t x1=zc_min(selecting_x1,selecting_x2);
2719 int32_t x2=zc_max(selecting_x1,selecting_x2);
2720 int32_t y1=zc_min(selecting_y1,selecting_y2);
2721 int32_t y2=zc_max(selecting_y1,selecting_y2);
2722
2723 if(select_mode==0)
2724 {
2725 clear_selection_grid();
2726 }
2727
2728 for(int32_t x=x1; x<=x2; ++x)
2729 {
2730 for(int32_t y=y1; y<=y2; ++y)
2731 {
2732 selection_grid[x+1][y+1]=((select_mode<2)?(1):(((select_mode==2)?(0):(selection_grid[x+1][y+1]))));
2733 }
2734 }
2735
2736 if(select_mode==3)
2737 {
2738 for(int32_t y=0; y<16; ++y)
2739 {
2740 for(int32_t x=0; x<x1; ++x)
2741 {
2742 selection_grid[x+1][y+1]=0;
2743 }
2744
2745 for(int32_t x=x2+1; x<16; ++x)
2746 {
2747 selection_grid[x+1][y+1]=0;
2748 }
2749 }
2750
2751 for(int32_t x=x1; x<=x2; ++x)
2752 {
2753 for(int32_t y=0; y<y1; ++y)
2754 {
2755 selection_grid[x+1][y+1]=0;
2756 }
2757
2758 for(int32_t y=y2+1; y<16; ++y)
2759 {
2760 selection_grid[x+1][y+1]=0;
2761 }
2762 }
2763 }
2764 }
2765
2766 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2767 did_wand_select=false;
2768 }
2769
2770 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
2771 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2772 bool ctrl=CHECK_CTRL_CMD;
2773 static int32_t last_tool_val = 0;
2774
2775 if(tool==t_select||tool==t_wand)
2776 {
2777 if(!drawing)
2778 {
2779 int32_t type=0;
2780
2781 if(has_selection())
2782 {
2783 if(shift)
2784 {
2785 type+=1;
2786 }
2787
2788 if(alt)
2789 {
2790 type+=2;
2791 }
2792 }
2793
2794 if(type!=select_mode)
2795 {
2796 select_mode=type;
2797
2798 if(isinRect(temp_mouse_x,temp_mouse_y-(tool==t_fill ? (14) : 0),zoomtile.x,zoomtile.y,zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2799 set_tool_sprite(tool,type);
2800 }
2801 }
2802 }
2803 else if(alt||ctrl)
2804 {
2805 if(old_tool==-1)
2806 {
2807 old_tool = tool;
2808 tool_cur = -1;
2809 }
2810 if(alt&&ctrl)
2811 tool = t_recolor;
2812 else if(alt)
2813 tool = t_eyedropper;
2814 else tool = t_fill;
2815 }
2816 else if(old_tool!=-1)
2817 {
2818 tool = old_tool;
2819 old_tool = -1;
2820 tool_cur = -1;
2821 redraw = true;
2822 }
2823 if(last_tool_val != tool)
2824 {
2825 redraw = true;
2826 tool_cur = -1;
2827 update_tool_cursor();
2828 last_tool_val = tool;
2829 }
2830
2831 if(!bdown)
2832 {
2833 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2834 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2835 }
2836
2837 if(gui_mouse_b()==1 && !bdown) //pressed the left mouse button
2838 {
2839 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2840 {
2841 if(tool==t_move || tool==t_fill)
2842 {
2843 set_tool_sprite(tool,1);
2844
2845 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2846 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2847 }
2848
2849 for(int32_t i=0; i<undocount; i++)
2850 {
2851 undotile[i]=newtilebuf[tile].data[i];
2852 }
2853 for(auto x = 0; x < 16; ++x)
2854 for(auto y = 0; y < 16; ++y)
2855 undoselgrid[x][y] = selection_grid[x+1][y+1];
2856 for(auto q = 0; q < 256; ++q)
2857 undofloatsel[q] = floatsel[q];
2858 undo_is_floatsel = floating_sel;
2859
2860 drawing=1;
2861 }
2862
2863 if(ok_button.rect(temp_mouse_x,temp_mouse_y))
2864 {
2865 if(do_text_button(ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK"))
2866 {
2867 done=2;
2868 }
2869 }
2870
2871 if(cancel_button.rect(temp_mouse_x,temp_mouse_y))
2872 {
2873 if(do_text_button(cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel"))
2874 {
2875 done=1;
2876 }
2877 }
2878
2879 if(edit_button.rect(temp_mouse_x,temp_mouse_y))
2880 {
2881 if(do_text_button(edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal"))
2882 {
2883 colors_menu.pop(edit_button.x+2,edit_button.y-40);
2884 get_palette(tpal);
2885
2886 if(newtilebuf[tile].format==tf4Bit)
2887 {
2888 invcol=makecol8(255 - tpal[CSET(cs)].r, 255 - tpal[CSET(cs)].g, 255 - tpal[CSET(cs)].b);
2889 }
2890 else
2891 {
2892 invcol=makecol8(255 - tpal[0].r, 255 - tpal[0].g, 255 - tpal[0].b);
2893 }
2894
2895 redraw=true;
2896 }
2897 }
2898
2899 int sqr_clicked;
2900 if(show_quartgrid && qgrid_tool(tool))
2901 {
2902 sqr_clicked = reflbtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2903 if(sqr_clicked > -1)
2904 {
2905 auto& sqr = reflbtn_grid.subsquare(sqr_clicked);
2906 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[sqr_clicked]))
2907 refl_flags ^= (1<<sqr_clicked);
2908 }
2909 }
2910 sqr_clicked = xmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2911 if(sqr_clicked > -1)
2912 {
2913 auto& sqr = xmodebtn_grid.subsquare(sqr_clicked);
2914 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[sqr_clicked]))
2915 xmode = sqr_clicked;
2916 }
2917 sqr_clicked = bgmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2918 if(sqr_clicked > -1)
2919 {
2920 auto& sqr = bgmodebtn_grid.subsquare(sqr_clicked);
2921 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[sqr_clicked]))
2922 bgmode = sqr_clicked;
2923 }
2924
2925 if(showcolortip)
2926 {
2927 auto oy = color_info.y;
2928 if(reftile <= 0)
2929 color_info.y -= ref_til.h + 8;
2930 if(color_info.rect(temp_mouse_x,temp_mouse_y))
2931 {
2932 showcolortip = 0;
2933 zc_set_config("ZQ_GUI","tile_edit_colornames",0);
2934 }
2935 color_info.y = oy;
2936 }
2937 else
2938 {
2939 auto oy = color_info_btn.y;
2940 if(reftile <= 0)
2941 color_info_btn.y -= ref_til.h + 8;
2942 if(color_info_btn.rect(temp_mouse_x,temp_mouse_y))
2943 {
2944 if(do_text_button(color_info_btn.x,color_info_btn.y,color_info_btn.w,color_info_btn.h,"Show Colors"))
2945 {
2946 showcolortip = 1;
2947 zc_set_config("ZQ_GUI","tile_edit_colornames",1);
2948 redraw=true;
2949 }
2950 }
2951 color_info_btn.y = oy;
2952 }
2953
2954 if(hlcbox.rect(temp_mouse_x,temp_mouse_y))
2955 {
2956 if(do_checkbox(screen2,hlcbox.x,hlcbox.y,hlcbox.w,hlcbox.h,tthighlight))
2957 {
2958 zc_set_config("ZQ_GUI","tile_edit_fancyhighlight",tthighlight);
2959 redraw=true;
2960 }
2961 }
2962 if(quartgrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2963 {
2964 if(do_checkbox(screen2,quartgrid_cbox.x,quartgrid_cbox.y,quartgrid_cbox.w,quartgrid_cbox.h,show_quartgrid))
2965 redraw=true;
2966 }
2967 if(hidegrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2968 {
2969 if(do_checkbox(screen2,hidegrid_cbox.x,hidegrid_cbox.y,hidegrid_cbox.w,hidegrid_cbox.h,hide_grid))
2970 redraw=true;
2971 }
2972
2973 switch(newtilebuf[tile].format)
2974 {
2975 case tf4Bit:
2976 {
2977 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
2978 if(ind > -1)
2979 {
2980 c1 = ind;
2981 redraw=true;
2982 }
2983 break;
2984 }
2985 case tf8Bit:
2986 {
2987 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
2988 if(ind > -1)
2989 {
2990 c1 = ind;
2991 redraw=true;
2992 }
2993 break;
2994 }
2995 }
2996
2997
2998 int32_t newtool = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
2999 if(newtool > -1 && newtool < t_max)
3000 {
3001 tool=newtool;
3002 redraw=true;
3003 }
3004
3005 if(x_btn.rect(temp_mouse_x,temp_mouse_y))
3006 {
3007 if(do_x_button(screen, x_btn.x, x_btn.y))
3008 {
3009 done=1;
3010 }
3011 }
3012 if(info_btn.rect(temp_mouse_x,temp_mouse_y))
3013 {
3014 if(do_question_button(screen, info_btn.x, info_btn.y))
3015 {
3016 show_edit_tile_help();
3017 }
3018 }
3019
3020 bdown=true;
3021 }
3022
3023 if(gui_mouse_b()&2 && !bdown) //pressed the right mouse button
3024 {
3025 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3026 {
3027 if(tool==t_move || tool==t_fill)
3028 {
3029 set_tool_sprite(tool,1);
3030
3031 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
3032 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
3033 }
3034
3035 for(int32_t i=0; i<undocount; i++)
3036 {
3037 undotile[i]=newtilebuf[tile].data[i];
3038 }
3039 for(auto x = 0; x < 16; ++x)
3040 for(auto y = 0; y < 16; ++y)
3041 undoselgrid[x][y] = selection_grid[x+1][y+1];
3042 for(auto q = 0; q < 256; ++q)
3043 undofloatsel[q] = floatsel[q];
3044 undo_is_floatsel = floating_sel;
3045
3046 drawing=2;
3047 }
3048
3049 switch(newtilebuf[tile].format)
3050 {
3051 case tf4Bit:
3052 {
3053 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
3054 if(ind > -1)
3055 {
3056 c2 = ind;
3057 redraw=true;
3058 }
3059 break;
3060 }
3061 case tf8Bit:
3062 {
3063 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
3064 if(ind > -1)
3065 {
3066 c2 = ind;
3067 redraw=true;
3068 }
3069 break;
3070 }
3071 }
3072
3073 bdown=true;
3074 }
3075
3076 if(bdown&&!gui_mouse_b()) //released the buttons
3077 {
3078 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3079 {
3080 if(tool==t_move || tool==t_fill)
3081 {
3082 set_tool_sprite(tool,0);
3083 }
3084 }
3085 }
3086
3087 if(drawing && zoomtile.rect(temp_mouse_x,temp_mouse_y)) //inside the zoomed tile window
3088 {
3089 int32_t ind = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3090 int32_t x=ind%zoomtile.w;
3091 int32_t y=ind/zoomtile.w;
3092
3093 bool reset_draw = false;
3094
3095 if(__pixel_draw(x,y,tile,flip))
3096 reset_draw = true;
3097 if(show_quartgrid)
3098 {
3099 auto tmp_sel_mode = select_mode;
3100 if(tool == t_wand && select_mode == 0)
3101 select_mode = 1;
3102 if(qgrid_tool(tool))
3103 {
3104 if(refl_flags & (1<<REFL_HFLIP))
3105 if(__pixel_draw(15-x,y,tile,flip))
3106 reset_draw = true;
3107 if(refl_flags & (1<<REFL_VFLIP))
3108 if(__pixel_draw(x,15-y,tile,flip))
3109 reset_draw = true;
3110 //Diagonal flip and 180° rotation are the same!
3111 if(refl_flags & ((1<<REFL_DBLFLIP)|(1<<REFL_180)))
3112 if(__pixel_draw(15-x,15-y,tile,flip))
3113 reset_draw = true;
3114 if(refl_flags & (1<<REFL_90CW))
3115 if(__pixel_draw(15-y,x,tile,flip))
3116 reset_draw = true;
3117 if(refl_flags & (1<<REFL_90CCW))
3118 if(__pixel_draw(y,15-x,tile,flip))
3119 reset_draw = true;
3120 }
3121 select_mode = tmp_sel_mode;
3122 }
3123
3124 if(reset_draw)
3125 drawing = 0;
3126 redraw=true;
3127 }
3128
3129 if(gui_mouse_b()==0)
3130 {
3131 bdown=false;
3132 drawing=0;
3133 }
3134
3135 temp_x=(gui_mouse_x()-zoomtile.x)/zoomtile.xscale;
3136 temp_y=(gui_mouse_y()-zoomtile.y)/zoomtile.yscale;
3137
3138 {
3139 tile_x=temp_x;
3140 tile_y=temp_y;
3141 redraw=true;
3142 }
3143
3144 const char *toolnames[t_max]=
3145 {
3146 "Pen\nDraw Single Pixels", "Fill\nCtrl", "Replace Color\nCtrl+Alt", "Grab Color\nAlt", "Move\nMove Selections", "Select Pixels", "Select Color"
3147 };
3148
3149 int32_t toolbtn = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
3150 if(toolbtn > -1 && toolbtn < t_max)
3151 {
3152 int32_t column = toolbtn%tool_btns.w;
3153 int32_t row = toolbtn/tool_btns.w;
3154
3155 update_tooltip(temp_mouse_x,temp_mouse_y,tool_btns.x+(column*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale, toolnames[toolbtn]);
3156 redraw=true;
3157 }
3158 /* Highlight the hovered pixel? Eh, maybe too much?
3159 int32_t hov_pix = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3160 if(hov_pix > -1)
3161 {
3162 int32_t column = hov_pix%zoomtile.w;
3163 int32_t row = hov_pix/zoomtile.w;
3164
3165 update_tooltip(temp_mouse_x,temp_mouse_y,zoomtile.x+(column*zoomtile.xscale),zoomtile.y+(row*zoomtile.yscale),zoomtile.xscale,zoomtile.yscale, NULL);
3166 redraw=true;
3167 }*/
3168
3169 if(redraw)
3170 {
3171 custom_vsync();
3172 draw_edit_scr(tile,flip,cs,oldtile, false);
3173 }
3174 else
3175 {
3176 bool hs=has_selection();
3177
3178 if(hs)
3179 {
3180 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
3181 }
3182
3183 custom_vsync();
3184
3185 if(hs)
3186 {
3187 // blit(screen2, screen, 79, 31, 79, 31, 129, 129);
3188 blit(screen2, screen, zoomtile.x-1,zoomtile.y-1, zoomtile.x-1,zoomtile.y-1, (zoomtile.w*zoomtile.xscale)+1, (zoomtile.h*zoomtile.yscale)+1);
3189 }
3190
3191 update_tool_cursor();
3192 SCRFIX();
3193 }
3194
3195 }
3196 while(!done);
3197
3198 unfloat_selection();
3199 clear_selection_grid();
3200
3201 while(gui_mouse_b())
3202 {
3203 /* do nothing */
3204 rest(1);
3205 }
3206
3207 if(done==1)
3208 {
3209 for(int32_t i=0; i<undocount; i++)
3210 {
3211 newtilebuf[tile].data[i]=oldtile[i];
3212 }
3213 }
3214 else
3215 {
3216 byte *buf = new byte[undocount];
3217
3218 // put back old tile
3219 for(int32_t i=0; i<undocount; i++)
3220 {
3221 buf[i] = newtilebuf[tile].data[i];
3222 newtilebuf[tile].data[i] = oldtile[i];
3223 }
3224
3225 // go
3226 go_tiles();
3227
3228 // replace old tile with new one again
3229 for(int32_t i=0; i<undocount; i++)
3230 {
3231 newtilebuf[tile].data[i] = buf[i];
3232 }
3233
3234 saved=false;
3235
3236 if(buf!=NULL)
3237 {
3238 delete[] buf;
3239 }
3240 }
3241
3242 MouseSprite::set(ZQM_NORMAL);
3243 register_blank_tiles();
3244 register_used_tiles();
3245 clear_tooltip();
3246 comeback();
3247 destroy_bitmap(selection_pattern);
3248 destroy_bitmap(selecting_pattern);
3249 destroy_bitmap(intersection_pattern);
3250 font = oldfont;
3251 popup_zqdialog_end();
3252 }
3253
3254 /* Grab Tile Code */
3255
3256 enum recolorState { rcNone, rc4Bit, rc8Bit };
3257
3258 BITMAP* original_imagebuf_bitmap=NULL;
3259 void *imagebuf=NULL;
3260 int32_t imagebuf_bitmap_scale=0;
3261 #define IMAGEBUF_SCALE (imagebuf_bitmap_scale > 0 ? imagebuf_bitmap_scale : 1.0 / -imagebuf_bitmap_scale)
3262 int32_t imagesize=0;
3263 int32_t tilecount=0;
3264 int32_t imagetype=0;
3265 int32_t imagex,imagey,selx,sely;
3266 int32_t bp=4,grabmode=16,romofs=0,romtilemode=0, romtilecols=8;
3267 bool nesmode=false;
3268 int32_t grabmask=0;
3269 recolorState recolor=rcNone;
3270 PALETTE imagepal;
3271
3272 /* bestfit_color:
3273 * Searches a palette for the color closest to the requested R, G, B value.
3274 */
3275 int32_t bestfit_cset_color(int32_t cs, int32_t r, int32_t g, int32_t b)
3276 {
3277 int32_t bestMatch = 0; // Color with the lowest total difference so far
3278 float bestTotalDiff = 100000; // Total difference between requested color and bestMatch
3279 float bestHighDiff = 100000; // Greatest difference of R, G, B between requested color and bestMatch
3280
3281 for(int32_t i = 0; i < CSET_SIZE; i++)
3282 {
3283 byte *rgbByte;
3284
3285 // This seems to be right...
3286 if(cs==2 || cs==3 || cs==4)
3287 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + i) * 3;
3288 else if(cs==9)
3289 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + i) * 3;
3290 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3291 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + i) * 3;
3292 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3293 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + i) * 3;
3294 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3295 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + i) * 3;
3296 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3297 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + i) * 3;
3298 else
3299 rgbByte = colordata + (CSET(cs)+i)*3;
3300
3301 int32_t dr=r-*rgbByte;
3302 int32_t dg=g-*(rgbByte+1);
3303 int32_t db=b-*(rgbByte+2);
3304
3305 // Track both the total color difference and the single greatest
3306 // difference of R, G, B. The idea is that it's better to have
3307 // two or three small differences than one big one.
3308 // The differences are multiplied by different numbers to account
3309 // for the differences in perceived brightness of the three colors.
3310 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3311 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3312
3313 // Perfect match? Just stop here.
3314 if(totalDiff==0)
3315 return i;
3316
3317 if(totalDiff < bestTotalDiff || // Best match so far?
3318 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3319 {
3320 bestMatch=i;
3321 bestTotalDiff=totalDiff;
3322 bestHighDiff=highDiff;
3323 }
3324 }
3325
3326 return bestMatch;
3327 }
3328
3329 // Same as the above, but draws from all colors in CSets 0-11.
3330 int32_t bestfit_cset_color_8bit(int32_t r, int32_t g, int32_t b)
3331 {
3332 int32_t bestMatch = 0;
3333 float bestTotalDiff = 100000;
3334 float bestHighDiff = 100000;
3335
3336 for(int32_t i = 0; i < 192; i++) // 192 colors in CSets 0-11
3337 {
3338 byte *rgbByte;
3339
3340 int32_t cs=i>>4;
3341 if(cs==2 || cs==3 || cs==4)
3342 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + (i%16)) * 3;
3343 else if(cs==9)
3344 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + (i%16)) * 3;
3345 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3346 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + (i%16)) * 3;
3347 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3348 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + (i%16)) * 3;
3349 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3350 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + (i%16)) * 3;
3351 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3352 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + (i%16)) * 3;
3353 else
3354 rgbByte = colordata + i * 3;
3355
3356 int32_t dr=r-*rgbByte;
3357 int32_t dg=g-*(rgbByte+1);
3358 int32_t db=b-*(rgbByte+2);
3359
3360 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3361 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3362
3363 if(totalDiff==0) // Perfect match?
3364 return i;
3365
3366 if(totalDiff < bestTotalDiff || // Best match so far?
3367 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3368 {
3369 bestMatch=i;
3370 bestTotalDiff=totalDiff;
3371 bestHighDiff=highDiff;
3372 }
3373 }
3374
3375 return bestMatch;
3376 }
3377
3378 byte cset_reduce_table[PAL_SIZE];
3379
3380 void calc_cset_reduce_table(PALETTE pal, int32_t cs)
3381 {
3382 for(int32_t i=0; i<PAL_SIZE; i++)
3383 {
3384 cset_reduce_table[i]=(bestfit_cset_color(cs, pal[i].r, pal[i].g, pal[i].b)&0x0F);
3385 }
3386 }
3387
3388 void calc_cset_reduce_table_8bit(PALETTE pal)
3389 {
3390 for(int32_t i=0; i<PAL_SIZE; i++)
3391 {
3392 cset_reduce_table[i]=bestfit_cset_color_8bit(pal[i].r, pal[i].g, pal[i].b);
3393 }
3394 }
3395
3396 void puttileROM(BITMAP *dest,int32_t x,int32_t y,byte *src,int32_t cs)
3397 {
3398 //storage space for the grabbed image
3399 byte buf[64];
3400 memset(buf,0,64);
3401 byte *oldsrc=src;
3402
3403 //for 8 lines in the source image...
3404 for(int32_t line=0; line<(nesmode?4:8); line++)
3405 {
3406 //bx is the pixel at the start of a line in the storage buffer
3407 int32_t bx=line<<(nesmode?4:3);
3408 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3409 byte b=src[(bp&1)?line:line<<1];
3410
3411 //fill the storage buffer with data from the source image
3412 for(int32_t i=7; i>=0; --i)
3413 {
3414 buf[bx+i] = (b&1)+(cs<<4);
3415 b>>=1;
3416 }
3417 }
3418
3419 ++src;
3420
3421 for(int32_t p=1; p<bp; p++)
3422 {
3423 for(int32_t line=0; line<(nesmode?4:8); line++)
3424 {
3425 int32_t bx=line<<(nesmode?4:3);
3426 byte b=src[(bp&1)?line:line<<1];
3427
3428 for(int32_t i=7; i>=0; --i)
3429 {
3430 if(nesmode)
3431 {
3432 buf[bx+8+i] = (b&1)+(cs<<4);
3433 }
3434 else
3435 {
3436 buf[bx+i] |= (b&1)<<p;
3437 }
3438
3439 b>>=1;
3440 }
3441 }
3442
3443 if(p&1)
3444 {
3445 src+=15;
3446 }
3447 else
3448 {
3449 ++src;
3450 }
3451 }
3452
3453
3454 if(nesmode)
3455 {
3456 src=oldsrc;
3457
3458 for(int32_t counter=0; counter<2; ++counter, ++src)
3459 {
3460 //for 8 lines in the source image...
3461 for(int32_t line=0; line<4; line++)
3462 {
3463 //bx is the pixel at the start of a line in the storage buffer
3464 int32_t bx=line<<4;
3465 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3466 byte b=src[(line+4)<<1];
3467
3468 //fill the storage buffer with data from the source image
3469 for(int32_t i=7; i>=0; --i)
3470 {
3471 // buf[bx+i] = (b&1)+(cs<<4);
3472 buf[bx+(counter<<3)+i] |= (b&1)<<1;
3473 b>>=1;
3474 }
3475 }
3476 }
3477 }
3478
3479 int32_t c=0;
3480
3481 switch(romtilemode)
3482 {
3483 case 0:
3484 case 1:
3485 case 2:
3486 for(int32_t j=0; j<8; j++)
3487 {
3488 for(int32_t i=0; i<8; i++)
3489 {
3490 putpixel(dest,x+i,y+j,buf[c++]);
3491 }
3492 }
3493
3494 break;
3495
3496 case 3:
3497 for(int32_t j=0; j<4; j++)
3498 {
3499 for(int32_t i=0; i<16; i++)
3500 {
3501 putpixel(dest,x+i,y+j,buf[c++]);
3502 }
3503 }
3504
3505 break;
3506 }
3507 }
3508
3509 const char *file_type[ftMAX]=
3510 {
3511 "None", "BIN", "BMP", "TIL", "ZGP", "QSU", "ZQT", "QST"
3512 };
3513
3514 void draw_grab_window()
3515 {
3516 int w = 640;
3517 int h = 480;
3518 int window_xofs=0;//(zq_screen_w-w-12)>>1;
3519 int window_yofs=0;//(zq_screen_h-h-25-6)>>1;
3520 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
3521 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+2+2-(79*2), FR_DEEP);
3522
3523 FONT *oldfont = font;
3524 font = get_zc_font(font_lfont);
3525 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Grab Tile(s)", true);
3526 font=oldfont;
3527 }
3528
3529 void draw_grab_scr(int32_t tile,int32_t cs,byte *newtile,int32_t black,int32_t white, int32_t width, int32_t height, byte *newformat)
3530 {
3531 width=width;
3532 height=height;
3533 white=white; // happy birthday compiler
3534
3535 int32_t yofs=0;
3536 //clear_to_color(screen2,bg);
3537 rectfill(screen2, 0, 0, 319, 159, black);
3538 rectfill(screen2,0,162,319,239,jwin_pal[jcBOX]);
3539 hline(screen2, 0, 160, 319, jwin_pal[jcMEDLT]);
3540 hline(screen2, 0, 161, 319, jwin_pal[jcLIGHT]);
3541 yofs=3;
3542
3543 // text_mode(-1);
3544 int32_t tileromcolumns=20;
3545
3546 switch(imagetype)
3547 {
3548 case ftBMP:
3549 if(recolor==rcNone)
3550 {
3551 blit((BITMAP*)imagebuf,screen2,imagex<<4,imagey<<4,0,0,320,160);
3552 }
3553 else
3554 {
3555 int32_t maxy=zc_min(160,((BITMAP*)imagebuf)->h);
3556 int32_t maxx=zc_min(320,((BITMAP*)imagebuf)->w);
3557
3558 for(int32_t y=0; y<maxy; y++)
3559 {
3560 if((imagey<<4)+y>=((BITMAP*)imagebuf)->h)
3561 {
3562 break;
3563 }
3564
3565 for(int32_t x=0; x<maxx; x++)
3566 {
3567 if((imagex<<4)+x>=((BITMAP*)imagebuf)->w)
3568 {
3569 break;
3570 }
3571
3572 if(recolor==rc8Bit)
3573 screen2->line[y][x]=cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]];
3574 else
3575 screen2->line[y][x]=(cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]])+(cs<<4);
3576 }
3577 }
3578 }
3579
3580 break;
3581
3582 case ftZGP:
3583 case ftQST:
3584 case ftZQT:
3585 case ftQSU:
3586 case ftTIL:
3587 {
3588 tiledata *hold = newtilebuf;
3589 newtilebuf = grabtilebuf;
3590 //fixme
3591 imagey = vbound(imagey, 0, MAXTILEROWS); //fixed -Z This can no longer crash if you scroll past the end of the tile pages. 6th June, 2020
3592 int32_t t=imagey*TILES_PER_ROW;
3593
3594 for(int32_t i=0; i<200; i++) // 10 rows, down to y=160
3595 {
3596 if(t <= tilecount)
3597 {
3598 puttile16(screen2,t,(i%TILES_PER_ROW)<<4,(i/TILES_PER_ROW)<<4,cs,0);
3599 }
3600
3601 ++t;
3602 }
3603
3604 newtilebuf = hold;
3605 //fixme
3606 }
3607 break;
3608
3609 case ftBIN:
3610 {
3611 int32_t ofs = (tileromcolumns*imagex + imagey) * 128*bp + romofs;
3612 byte *buf = (byte*)imagebuf;
3613
3614 switch(romtilemode)
3615 {
3616 case 0:
3617 for(int32_t y=0; y<160; y+=8)
3618 {
3619 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3620 {
3621 puttileROM(screen2,x,y,buf+ofs,cs);
3622 ofs+=8*bp;
3623 }
3624 }
3625
3626 for(int32_t y=0; y<160; y+=8)
3627 {
3628 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3629 {
3630 puttileROM(screen2,x+128,y,buf+ofs,cs);
3631 ofs+=8*bp;
3632 }
3633 }
3634
3635 break;
3636
3637 case 1:
3638 for(int32_t y=0; y<160; y+=16)
3639 {
3640 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3641 {
3642 puttileROM(screen2,x,y,buf+ofs,cs);
3643 ofs+=8*bp;
3644 puttileROM(screen2,x,y+8,buf+ofs,cs);
3645 ofs+=8*bp;
3646 }
3647 }
3648
3649 for(int32_t y=0; y<160; y+=16)
3650 {
3651 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3652 {
3653 puttileROM(screen2,x+128,y,buf+ofs,cs);
3654 ofs+=8*bp;
3655 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3656 ofs+=8*bp;
3657 }
3658 }
3659
3660 break;
3661
3662 case 2:
3663 for(int32_t y=0; y<160; y+=16)
3664 {
3665 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3666 {
3667 puttileROM(screen2,x,y,buf+ofs,cs);
3668 ofs+=8*bp;
3669 puttileROM(screen2,x+8,y,buf+ofs,cs);
3670 ofs+=8*bp;
3671 puttileROM(screen2,x,y+8,buf+ofs,cs);
3672 ofs+=8*bp;
3673 puttileROM(screen2,x+8,y+8,buf+ofs,cs);
3674 ofs+=8*bp;
3675 }
3676 }
3677
3678 for(int32_t y=0; y<160; y+=16)
3679 {
3680 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3681 {
3682 puttileROM(screen2,x+128,y,buf+ofs,cs);
3683 ofs+=8*bp;
3684 puttileROM(screen2,x+136,y,buf+ofs,cs);
3685 ofs+=8*bp;
3686 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3687 ofs+=8*bp;
3688 puttileROM(screen2,x+136,y+8,buf+ofs,cs);
3689 ofs+=8*bp;
3690 }
3691 }
3692
3693 break;
3694
3695 case 3:
3696 for(int32_t y=0; y<160; y+=16)
3697 {
3698 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3699 {
3700 puttileROM(screen2,x,y,buf+ofs,cs);
3701 ofs+=8*bp;
3702 puttileROM(screen2,x,y+4,buf+ofs,cs);
3703 ofs+=8*bp;
3704 puttileROM(screen2,x,y+8,buf+ofs,cs);
3705 ofs+=8*bp;
3706 puttileROM(screen2,x,y+12,buf+ofs,cs);
3707 ofs+=8*bp;
3708 }
3709 }
3710
3711 for(int32_t y=0; y<160; y+=16)
3712 {
3713 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3714 {
3715 puttileROM(screen2,x+128,y,buf+ofs,cs);
3716 ofs+=8*bp;
3717 puttileROM(screen2,x+128,y+4,buf+ofs,cs);
3718 ofs+=8*bp;
3719 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3720 ofs+=8*bp;
3721 puttileROM(screen2,x+128,y+12,buf+ofs,cs);
3722 ofs+=8*bp;
3723 }
3724 }
3725
3726 break;
3727 }
3728 }
3729 break;
3730 }
3731
3732 tiledata hold;
3733 bool holdblank = blank_tile_table[0];
3734
3735 if(is_valid_format(newtilebuf[0].format))
3736 {
3737 hold.format = newtilebuf[0].format;
3738 hold.data = (byte *)malloc(tilesize(hold.format));
3739 memcpy(hold.data, newtilebuf[0].data, tilesize(hold.format));
3740 }
3741 else
3742 {
3743 hold.format=tfInvalid;
3744 hold.data=NULL;
3745 }
3746
3747 newtilebuf[0].format=newformat[0];
3748 blank_tile_table[0] = false;
3749
3750 if(newtilebuf[0].data!=NULL)
3751 {
3752 free(newtilebuf[0].data);
3753 }
3754
3755 if(is_valid_format(newtilebuf[0].format))
3756 {
3757 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3758
3759 for(int32_t i=0; i<tilesize(newtilebuf[0].format); i++)
3760 {
3761 newtilebuf[0].data[i]=newtile[i];
3762 }
3763 }
3764 else
3765 {
3766 newtilebuf[0].data=NULL;
3767 }
3768
3769 puttile16(screen2,0,208,168+yofs,cs,0);
3770 overtile16(screen2,0,232,168+yofs,cs,0);
3771 newtilebuf[0].format=hold.format;
3772 blank_tile_table[0] = holdblank;
3773
3774 if(newtilebuf[0].data!=NULL)
3775 {
3776 free(newtilebuf[0].data);
3777 }
3778
3779 if(is_valid_format(newtilebuf[0].format))
3780 {
3781 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3782
3783 for(int32_t i=0; i<256; i++)
3784 {
3785 newtilebuf[0].data[i]=hold.data[i];
3786 }
3787 }
3788 else
3789 {
3790 newtilebuf[0].data=NULL;
3791 }
3792
3793 if(hold.data!=NULL)
3794 {
3795 free(hold.data);
3796 }
3797
3798 puttile16(screen2,tile,208,192+yofs,cs,0);
3799 overtile16(screen2,tile,232,192+yofs,cs,0);
3800
3801 rectfill(screen2,184,168+yofs,191,175+yofs,grabmask&1?vc(12):vc(7));
3802 rectfill(screen2,192,168+yofs,199,175+yofs,grabmask&2?vc(12):vc(7));
3803 rectfill(screen2,184,176+yofs,191,183+yofs,grabmask&4?vc(12):vc(7));
3804 rectfill(screen2,192,176+yofs,199,183+yofs,grabmask&8?vc(12):vc(7));
3805
3806 // rect(screen2,183,167,200,184,dvc(7*2));
3807 // rect(screen2,207,167,224,184,dvc(7*2));
3808 // rect(screen2,231,167,248,184,dvc(7*2));
3809 // rect(screen2,207,191,224,208,dvc(7*2));
3810 // rect(screen2,231,191,248,208,dvc(7*2));
3811
3812 /*
3813 rect(screen2,183,167,200,184,vc(14));
3814 rect(screen2,207,167,224,184,vc(14));
3815 rect(screen2,231,167,248,184,vc(14));
3816 rect(screen2,207,191,224,208,vc(14));
3817 rect(screen2,231,191,248,208,vc(14));
3818 */
3819 jwin_draw_frame(screen2,182,166+yofs,20,20,FR_DEEP);
3820 jwin_draw_frame(screen2,206,166+yofs,20,20,FR_DEEP);
3821 jwin_draw_frame(screen2,230,166+yofs,20,20,FR_DEEP);
3822 jwin_draw_frame(screen2,206,190+yofs,20,20,FR_DEEP);
3823 jwin_draw_frame(screen2,230,190+yofs,20,20,FR_DEEP);
3824 int32_t screen_xofs=6;
3825 int32_t screen_yofs=25;
3826 int winh = 511;
3827 int32_t mul = 2;
3828
3829 yofs=16;
3830
3831 custom_vsync();
3832
3833 stretch_blit(screen2,screen,0,0,320,240,screen_xofs,screen_yofs,640,480);
3834
3835 // Suspend the current font while draw_text_button does its work
3836 FONT* oldfont = font;
3837
3838 font = get_zc_font(font_lfont_l);
3839
3840 int txt_x = 8*mul;
3841 int rbtn_x = 255*mul;
3842 int max_fpath_wid = rbtn_x-2-txt_x;
3843 int max_fpath_wid2 = max_fpath_wid-text_length(font,"... ");
3844 // Interface
3845 switch(imagetype)
3846 {
3847 case 0:
3848 textprintf_ex(screen,font,txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s",imgstr[imagetype]);
3849 break;
3850
3851 case ftBMP:
3852 {
3853 std::string text = fmt::format("{} {}x{}, {:.2g}x zoom with , and .", imgstr[imagetype], original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, IMAGEBUF_SCALE);
3854 int text_x = txt_x;
3855 int text_y = (216 + yofs) * mul;
3856 // TODO: can almost use this, but drawing is offset. prob cuz drawing to a different bitmap than the normal screen bitmap? idk
3857 // int text_w = text_length(font, text.c_str());
3858 // int text_h = text_height(font);
3859 // static int grab_scale_tooltip_id = ttip_register_id();
3860 // ttip_install(grab_scale_tooltip_id, "zoom with , and .", text_x, text_y, text_w, text_h, text_x, text_y - 40);
3861 textprintf_ex(screen, font, text_x, text_y, jwin_pal[jcTEXTFG], jwin_pal[jcBOX], "%s", text.c_str());
3862
3863 draw_text_button(screen,117*mul,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Recolor",vc(1),vc(14),0,true);
3864 break;
3865 }
3866
3867 case ftZGP:
3868 case ftQST:
3869 case ftZQT:
3870 case ftQSU:
3871 case ftTIL:
3872 case ftBIN:
3873 textprintf_ex(screen,get_zc_font(font_lfont_l),txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s %d KB",imgstr[imagetype],imagesize>>10);
3874 break;
3875 }
3876
3877 textprintf_ex(screen,font,txt_x,(168+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"sel: %d %d",selx,sely);
3878 textprintf_ex(screen,font,txt_x,(176+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"pos: %d %d",imagex,imagey);
3879
3880 if(bp==8)
3881 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"8-bit");
3882 else
3883 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"cset: %d",cs);
3884 textprintf_ex(screen,font,txt_x,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"step: %d",grabmode);
3885
3886 if(imagetype==ftBIN)
3887 {
3888 textprintf_ex(screen,font,104*mul,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"bp: %d%s",bp,nesmode?" (NES)":"");
3889 textprintf_ex(screen,font,104*mul,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"ofs: %Xh",romofs);
3890 textprintf_ex(screen,font,104*mul,(208+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"m: %d",romtilemode);
3891 }
3892
3893 int fpath_y = (224+yofs)*mul;
3894 if(text_length(font,imagepath) <= max_fpath_wid)
3895 textout_ex(screen,font,imagepath,txt_x,fpath_y,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3896 else
3897 {
3898 char buf[2052] = {0};
3899 strncpy(buf,imagepath,2048);
3900 int len = strlen(buf);
3901 char *ptr = buf;
3902 char *endptr = buf+len;
3903 char *it = endptr;
3904 int tmpy = fpath_y;
3905 int tmph = text_height(font)+1;
3906 while(true)
3907 {
3908 if(tmpy+tmph > (winh-2))
3909 break; //Out of space!
3910 char c = *it;
3911 bool end = !c;
3912 *it = 0;
3913 int newlen = text_length(font,ptr);
3914 if(newlen <= (end ? max_fpath_wid : max_fpath_wid2))
3915 {
3916 if(end) //No stored character, string ended
3917 {
3918 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3919 break;
3920 }
3921 char t[5];
3922 t[0] = c;
3923 for(int q = 1; q < 5; ++q)
3924 t[q] = it[q];
3925 strcpy(it,"...");
3926 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3927 for(int q = 0; q < 5; ++q)
3928 it[q] = t[q];
3929 tmpy += tmph;
3930 ptr = it;
3931 it = endptr;
3932 }
3933 else
3934 {
3935 *it = c;
3936 --it;
3937 }
3938 }
3939 }
3940 draw_text_button(screen,rbtn_x,(168+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"OK",vc(1),vc(14),0,true);
3941 draw_text_button(screen,rbtn_x,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Cancel",vc(1),vc(14),0,true);
3942 draw_text_button(screen,rbtn_x,(216+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"File",vc(1),vc(14),0,true);
3943 draw_text_button(screen,117*mul,(166+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Leech",vc(1),vc(14),0,true);
3944
3945 //int32_t rectw = 16*mul;
3946 //rect(screen,selx+screen_xofs,sely+screen_yofs,selx+screen_xofs+((width-1)*rectw)+rectw-1,sely+screen_yofs+((height-1)*rectw)+rectw-1,white);
3947 SCRFIX();
3948 font = oldfont;
3949 }
3950
3951 RGB_MAP rgb_table;
3952 COLOR_MAP imagepal_table;
3953
3954
3955 extern void return_RAMpal_color(AL_CONST PALETTE pal, int32_t x, int32_t y, RGB *rgb)
3956 {
3957 //these are here to bypass compiler warnings about unused arguments
3958 x=x;
3959
3960 rgb->r = pal[y].r;
3961 rgb->g = pal[y].g;
3962 rgb->b = pal[y].b;
3963 }
3964
3965
3966 void load_imagebuf()
3967 {
3968 PACKFILE *f;
3969 //cache QRS
3970 //byte cached_rules[QUESTRULES_NEW_SIZE] = { 0 };
3971 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
3972 // {
3973 // cached_rules[q] = quest_rules[q];
3974 // }
3975 bool compressed=false;
3976 bool encrypted=false;
3977 tiledata *hold=newtilebuf;
3978 zquestheader tempheader{};
3979
3980 if(imagebuf)
3981 {
3982 switch(imagetype)
3983 {
3984 case ftBMP:
3985 if (original_imagebuf_bitmap != imagebuf)
3986 destroy_bitmap((BITMAP*)imagebuf);
3987 destroy_bitmap(original_imagebuf_bitmap);
3988 break;
3989
3990 case ftZGP:
3991 case ftQST:
3992 case ftZQT:
3993 case ftQSU:
3994 case ftTIL:
3995 clear_tiles(grabtilebuf);
3996 break;
3997
3998 case ftBIN:
3999 free(imagebuf);
4000 break;
4001 }
4002
4003 imagebuf=NULL;
4004 original_imagebuf_bitmap=NULL;
4005 }
4006
4007 selx=sely=romofs=0;
4008 bp=4;
4009 imagetype=filetype(imagepath);
4010
4011 dword section_id;
4012 word section_version;
4013
4014 switch(imagetype)
4015 {
4016 case ftBMP:
4017 packfile_password("");
4018 memset(imagepal, 0, sizeof(PALETTE));
4019 original_imagebuf_bitmap = load_bitmap(imagepath,imagepal);
4020 imagesize = file_size_ex_password(imagepath,"");
4021 tilecount=0;
4022 create_rgb_table(&rgb_table, imagepal, NULL);
4023 rgb_map = &rgb_table;
4024 create_color_table(&imagepal_table, RAMpal, return_RAMpal_color, NULL);
4025
4026 if(!original_imagebuf_bitmap)
4027 {
4028 imagetype=0;
4029 }
4030 else
4031 {
4032 imagebuf = original_imagebuf_bitmap;
4033 imagebuf_bitmap_scale = 1;
4034 }
4035
4036 break;
4037
4038 case ftBIN:
4039 packfile_password("");
4040 imagesize = file_size_ex_password(imagepath, "");
4041 tilecount=0;
4042
4043 if(imagesize)
4044 {
4045 imagebuf = malloc(imagesize);
4046
4047 if(!readfile(imagepath,imagebuf,imagesize))
4048 {
4049 free(imagebuf);
4050 imagesize=0;
4051 imagetype=0;
4052 }
4053 }
4054
4055 break;
4056
4057 case ftTIL:
4058 packfile_password("");
4059 imagesize = file_size_ex_password(imagepath,"");
4060 f = pack_fopen_password(imagepath,F_READ,"");
4061
4062 if(!f)
4063 {
4064 goto error;
4065 }
4066
4067 if(!p_mgetl(&section_id,f))
4068 {
4069 goto error;
4070 }
4071
4072 if(section_id==ID_TILES)
4073 {
4074 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)==0)
4075 {
4076 goto error;
4077 }
4078 }
4079
4080 error:
4081 pack_fclose(f);
4082 tilecount=count_tiles(grabtilebuf);
4083 break;
4084
4085 case ftZGP:
4086 packfile_password("");
4087 imagesize = file_size_ex_password(imagepath, "");
4088 f=pack_fopen_password(imagepath,F_READ,"");
4089
4090 if(!f)
4091 {
4092 goto error2;
4093 }
4094
4095 if(!p_mgetl(&section_id,f))
4096 {
4097 goto error2;
4098 }
4099
4100 if(section_id!=ID_GRAPHICSPACK)
4101 {
4102 goto error2;
4103 }
4104
4105 //section version info
4106 if(!p_igetw(&section_version,f))
4107 {
4108 goto error2;
4109 }
4110
4111 if(!read_deprecated_section_cversion(f))
4112 {
4113 goto error2;
4114 }
4115
4116 //tiles
4117 if(!p_mgetl(&section_id,f))
4118 {
4119 goto error2;
4120 }
4121
4122 if(section_id==ID_TILES)
4123 {
4124 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)!=0)
4125 {
4126 goto error2;
4127 }
4128 }
4129
4130 error2:
4131 pack_fclose(f);
4132 tilecount=count_tiles(grabtilebuf);
4133 break;
4134
4135 case ftQST:
4136 encrypted=true;
4137 case ftZQT:
4138 compressed=true;
4139 case ftQSU:
4140 packfile_password("");
4141 imagesize = file_size_ex_password(imagepath, encrypted ? datapwd : "");
4142 newtilebuf=grabtilebuf;
4143 byte skip_flags[4];
4144
4145 for(int32_t i=0; i<skip_max; ++i)
4146 {
4147 set_bit(skip_flags,i,1);
4148 }
4149
4150 set_bit(skip_flags,skip_tiles,0);
4151 set_bit(skip_flags,skip_header,0);
4152 int ret = loadquest(imagepath,&tempheader,&QMisc,customtunes,true,skip_flags);
4153 if (ret)
4154 {
4155 imagetype=0;
4156 imagesize=0;
4157 clear_tiles(grabtilebuf);
4158 chop_path(imagepath);
4159 }
4160
4161 if (!ret && encrypted && compressed)
4162 {
4163 if(quest_access(imagepath, &tempheader) != 1)
4164 {
4165 imagetype=0;
4166 imagesize=0;
4167 clear_tiles(grabtilebuf);
4168 chop_path(imagepath);
4169 }
4170 }
4171
4172 //setPackfilePassword(NULL);
4173 newtilebuf=hold;
4174 tilecount=count_tiles(grabtilebuf);
4175 break;
4176 }
4177
4178 rgb_map = &zq_rgb_table;
4179 //restore cashed QRs / rules
4180
4181 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
4182 // {
4183 // quest_rules[q] = cached_rules[q];
4184 // }
4185 }
4186
4187 static char bitstrbuf[32];
4188 bool leeching_from_tiles=false;
4189
4190 const char *bitlist(int32_t index, int32_t *list_size)
4191 {
4192 int32_t imported=2;
4193
4194 if(index>=0)
4195 {
4196 bound(index,0,leeching_from_tiles?2:1);
4197
4198 if(index==imported)
4199 {
4200 sprintf(bitstrbuf,"Imported");
4201 }
4202 else
4203 {
4204 sprintf(bitstrbuf,"%d",4<<index);
4205 }
4206
4207 return bitstrbuf;
4208 }
4209
4210 *list_size=leeching_from_tiles?3:2;
4211 return NULL;
4212 }
4213
4214 12 static ListData bit_list(bitlist, &font);
4215
4216 static DIALOG leech_dlg[] =
4217 {
4218 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
4219 12 { jwin_win_proc, 8, 20-4, 303+1, 216-42+1, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Leech Options", NULL, NULL },
4220 12 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
4221 // 2
4222 12 { jwin_button_proc, 180, 210-42-4, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
4223 12 { jwin_button_proc, 80, 210-42-4, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
4224 12 { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL },
4225 // 5
4226 12 { jwin_text_proc, 14, 49-4, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Update Status Every: ", NULL, NULL },
4227 12 { jwin_edit_proc, 114, 45-4, 36, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL },
4228 12 { jwin_radio_proc, 155, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Tiles", NULL, NULL },
4229 12 { jwin_radio_proc, 200, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Seconds", NULL, NULL },
4230 //9
4231 12 { jwin_frame_proc, 14, 63-2, 176+70, 50+30, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL },
4232 12 { jwin_text_proc, 14+8, 60-2, 80, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) " Duplicates ", NULL, NULL },
4233
4234 12 { jwin_check_proc, 20, 70, 168, 8+1, vc(15), vc(1), 0, 0, 1, 0, (void *) "Only check new tiles", NULL, NULL },
4235 12 { jwin_text_proc, 20, 90, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Normal:", NULL, NULL },
4236 12 { jwin_text_proc, 20, 100, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal Flip:", NULL, NULL },
4237 12 { jwin_text_proc, 20, 110, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Vertical Flip:", NULL, NULL },
4238 12 { jwin_text_proc, 20, 120, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal/Vertical Flip:", NULL, NULL },
4239 //16
4240 12 { jwin_radio_proc, 144, 90, 64+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4241 12 { jwin_radio_proc, 184, 90, 56+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4242 12 { jwin_radio_proc, 224, 90, 72+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4243
4244 12 { jwin_radio_proc, 144, 100, 64+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4245 12 { jwin_radio_proc, 184, 100, 56+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4246 12 { jwin_radio_proc, 224, 100, 72+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4247
4248 12 { jwin_radio_proc, 144, 110, 64+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4249 12 { jwin_radio_proc, 184, 110, 56+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4250 12 { jwin_radio_proc, 224, 110, 72+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4251
4252 12 { jwin_radio_proc, 144, 120, 64+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4253 12 { jwin_radio_proc, 184, 120, 56+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4254 12 { jwin_radio_proc, 224, 120, 72+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4255
4256 12 { jwin_ctext_proc, 144+4, 80, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Ignore", NULL, NULL },
4257 12 { jwin_ctext_proc, 184+4, 80, 56+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Check", NULL, NULL },
4258 12 { jwin_ctext_proc, 224+4, 80, 72+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Discard", NULL, NULL },
4259 12 { jwin_droplist_proc, 76, 145, 80, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &bit_list, NULL, NULL },
4260 12 { jwin_text_proc, 14, 149, 60, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Color Depth: ", NULL, NULL },
4261 12 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
4262 };
4263
4264 bool leech_tiles(tiledata *dest,int32_t start,int32_t cs)
4265 {
4266 bool shift=true; // fix this!
4267 int32_t cst=0;
4268 int32_t currtile=start;
4269 int32_t height=0, width=0;
4270 byte *testtile = new byte[tilesize(tf32Bit)];
4271 byte imported_format=0;
4272 char updatestring[6];
4273 bool canadd;
4274 bool temp_canadd;
4275 bool duplicate;
4276 int32_t total_duplicates_found=0, total_duplicates_discarded=0;
4277 int32_t duplicates_found[4]= //, duplicates_discarded[4]={0,0,0,0};
4278 {
4279 0,0,0,0
4280 };
4281 BITMAP *status;
4282 status = create_bitmap_ex(8,240,140);
4283 clear_bitmap(status);
4284 sprintf(updatestring, "%d", LeechUpdate);
4285 leech_dlg[0].dp2=get_zc_font(font_lfont);
4286 leech_dlg[6].dp=updatestring;
4287
4288 leech_dlg[10].flags=(OnlyCheckNewTilesForDuplicates!=0) ? D_SELECTED : 0;
4289
4290 for(int32_t i=0; i<2; i++)
4291 {
4292 leech_dlg[i+7].flags=0;
4293 }
4294
4295 leech_dlg[7+((LeechUpdateTiles==0) ? 1 : 0)].flags=D_SELECTED;
4296
4297 for(int32_t i=0; i<12; i++)
4298 {
4299 leech_dlg[i+16].flags=0;
4300 }
4301
4302 for(int32_t i=0; i<4; i++)
4303 {
4304 leech_dlg[(DuplicateAction[i])+16+(i*3)].flags=D_SELECTED;
4305 }
4306
4307 leech_dlg[31].d1=0;
4308
4309 large_dialog(leech_dlg);
4310
4311 int32_t ret = do_zqdialog(leech_dlg,3);
4312
4313 if(ret==2)
4314 {
4315 delete[] testtile;
4316 return false;
4317 }
4318
4319 int32_t cdepth=leech_dlg[31].d1+1;
4320 int32_t newformat=0;
4321 auto lu = atoi(updatestring);
4322 auto lut = (leech_dlg[7].flags&D_SELECTED)?1:0;
4323 if(LeechUpdate!=lu)
4324 {
4325 LeechUpdate=lu;
4326 zc_set_config("zquest","leech_update",LeechUpdate);
4327 }
4328 if(LeechUpdateTiles!=lut)
4329 {
4330 LeechUpdateTiles=lut;
4331 zc_set_config("zquest","leech_update_tiles",LeechUpdateTiles);
4332 }
4333
4334 int32_t old_dupe[4];
4335 for(int32_t j=0; j<4; j++)
4336 {
4337 old_dupe[j] = DuplicateAction[j];
4338 for(int32_t i=0; i<3; i++)
4339 {
4340 if(leech_dlg[i+16+(j*3)].flags&D_SELECTED)
4341 {
4342 DuplicateAction[j]=i;
4343 }
4344 }
4345 }
4346 if(old_dupe[0] != DuplicateAction[0])
4347 zc_set_config("zquest","normal_duplicate_action",DuplicateAction[0]);
4348 if(old_dupe[1] != DuplicateAction[1])
4349 zc_set_config("zquest","horizontal_duplicate_action",DuplicateAction[1]);
4350 if(old_dupe[2] != DuplicateAction[2])
4351 zc_set_config("zquest","vertical_duplicate_action",DuplicateAction[2]);
4352 if(old_dupe[3] != DuplicateAction[3])
4353 zc_set_config("zquest","both_duplicate_action",DuplicateAction[3]);
4354
4355 auto ocntfd = leech_dlg[10].flags&D_SELECTED?1:0;
4356 if(OnlyCheckNewTilesForDuplicates!=ocntfd)
4357 {
4358 OnlyCheckNewTilesForDuplicates=ocntfd;
4359 zc_set_config("zquest","only_check_new_tiles_for_duplicates",ocntfd);
4360 }
4361
4362 leeching_from_tiles=false;
4363
4364 switch(imagetype)
4365 {
4366 case ftBIN:
4367 width=imagesize/128;
4368 height=1;
4369 break;
4370
4371 case ftZGP:
4372 case ftQST:
4373 case ftZQT:
4374 case ftQSU:
4375 case ftTIL:
4376 leeching_from_tiles=true;
4377 width=count_tiles(grabtilebuf);
4378 height=1;
4379 break;
4380
4381 case ftBMP:
4382 width=((((BITMAP*)imagebuf)->w)+15)/16;
4383 height=((((BITMAP*)imagebuf)->h)+15)/16;
4384 break;
4385 }
4386
4387 if(currtile+(width*height)>NEWMAXTILES)
4388 {
4389 if(jwin_alert("Confirm Truncation","Too many tiles.","Truncation may occur.",NULL,"&OK","&Cancel",'o','c',get_zc_font(font_lfont))==2)
4390 {
4391 delete[] testtile;
4392 return false;
4393 }
4394 }
4395
4396 go_tiles();
4397 saved=false;
4398
4399 for(int32_t ty=0; ty<height; ty++) //for every row
4400 {
4401 for(int32_t tx=0; tx<width; tx++) //for every column (tile)
4402 {
4403 if((((ty*width)+tx)%zc_max(LeechUpdate, 1))==0) //update status
4404 {
4405 FONT *oldfont = font;
4406 static BITMAP *tbar = create_bitmap_ex(8,240-6, 18);
4407 static bool created_tbar=false;
4408 jwin_draw_win(status, 0, 0, 240, 140, FR_WIN);
4409
4410 if(created_tbar)
4411 {
4412 blit(tbar, status, 0, 0, 3, 3, 240-6, 18);
4413 }
4414 else
4415 {
4416 font = get_zc_font(font_lfont);
4417 jwin_draw_titlebar(tbar, 0, 0, 240-6, 18, "Leech Status", false);
4418 font = oldfont;
4419 created_tbar=true;
4420 blit(tbar, status, 0, 0, 3, 3, 320-6, 18);
4421 }
4422
4423 textprintf_centre_ex(status,font,120,24,jwin_pal[jcTEXTFG],-1,"Checking %d of %d",((ty*width)+tx), (width*height));
4424 textprintf_centre_ex(status,font,120,34,jwin_pal[jcTEXTFG],-1,"%d tiles imported",currtile-start);
4425 jwin_draw_frame(status, 40, 49, 160, 70, FR_ETCHED);
4426 textprintf_centre_ex(status,font,120,46,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]," Duplicates ");
4427 textprintf_centre_ex(status,font,120,56,jwin_pal[jcTEXTFG],-1,"%d/%d found/discarded",total_duplicates_found, total_duplicates_discarded);
4428 textprintf_centre_ex(status,font,120,76,jwin_pal[jcTEXTFG],-1,"%d normal %s",duplicates_found[0],((DuplicateAction[0]<2)?"found":"discarded"));
4429 textprintf_centre_ex(status,font,120,86,jwin_pal[jcTEXTFG],-1,"%d flipped (h) %s",duplicates_found[1],((DuplicateAction[1]<2)?"found":"discarded"));
4430 textprintf_centre_ex(status,font,120,96,jwin_pal[jcTEXTFG],-1,"%d flipped (v) %s",duplicates_found[2],((DuplicateAction[2]<2)?"found":"discarded"));
4431 textprintf_centre_ex(status,font,120,106,jwin_pal[jcTEXTFG],-1,"%d flipped (hv) %s",duplicates_found[3],((DuplicateAction[3]<2)?"found":"discarded"));
4432 textprintf_centre_ex(status,font,120,128,jwin_pal[jcTEXTFG],-1,"Press any key to stop.");
4433 blit(status,screen,0, 0, 40, 20, 240, 140);
4434 SCRFIX();
4435 }
4436
4437 canadd=true;
4438
4439 if(currtile>=NEWMAXTILES) //if we've maxed out on our tiles...
4440 {
4441 delete[] testtile;
4442 return true;
4443 }
4444
4445 switch(imagetype)
4446 {
4447 case ftBIN:
4448 break;
4449
4450 case ftZGP:
4451 case ftQST:
4452 case ftZQT:
4453 case ftQSU:
4454 case ftTIL:
4455 memset(testtile, 0, tilesize(tf32Bit));
4456 imported_format=grabtilebuf[tx].format;
4457
4458 switch(cdepth)
4459 {
4460 case 1: //4-bit
4461 newformat=tf4Bit;
4462
4463 switch(imported_format)
4464 {
4465 case tf4Bit:
4466 case tf8Bit:
4467 for(int32_t y=0; y<16; y++) //snag a tile
4468 {
4469 for(int32_t x=0; x<16; x+=2)
4470 {
4471 testtile[(y*8)+(x/2)]=
4472 (grabtilebuf[tx].data[y*16+x]&15)+
4473 ((grabtilebuf[tx].data[y*16+x+1]&15)<<4);
4474 }
4475 }
4476
4477 break;
4478 }
4479
4480 break;
4481
4482 case 2: //8-bit
4483 newformat=tf8Bit;
4484
4485 switch(imported_format)
4486 {
4487 case tf4Bit:
4488 unpack_tile(grabtilebuf, tx, 0, true);
4489 cst = cs&15;
4490 cst <<= CSET_SHFT;
4491
4492 for(int32_t i=0; i<256; i++)
4493 {
4494 if(!shift||unpackbuf[i]!=0)
4495 {
4496 unpackbuf[i]+=cst;
4497 }
4498 }
4499
4500 pack_tiledata(testtile, unpackbuf, tf8Bit);
4501 break;
4502
4503 case tf8Bit:
4504 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4505 break;
4506 }
4507
4508 break;
4509
4510 case 3: //original tile's bit depth
4511 newformat=imported_format;
4512 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4513 break;
4514 }
4515
4516 break;
4517
4518 case ftBMP:
4519 newformat=cdepth;
4520
4521 for(int32_t y=0; y<16; y++) //snag a tile
4522 {
4523 for(int32_t x=0; x<16; x+=2)
4524 {
4525 testtile[(y*16)+x]=getpixel(((BITMAP*)imagebuf),(tx*16)+x,(ty*16)+y);
4526 testtile[(y*16)+x+1]=getpixel(((BITMAP*)imagebuf),(tx*16)+x+1,(ty*16)+y);
4527 }
4528 }
4529
4530 break;
4531 }
4532
4533 if(DuplicateAction[0]+DuplicateAction[1]+DuplicateAction[2]+DuplicateAction[3]>0)
4534 {
4535 temp_canadd=true;
4536
4537 //check all tiles before this one
4538 for(int32_t checktile=((OnlyCheckNewTilesForDuplicates!=0)?start:0); ((temp_canadd==true)&&(checktile<currtile)); checktile++)
4539 {
4540 for(int32_t flipping=0; ((temp_canadd==true)&&(flipping<4)); ++flipping)
4541 {
4542 if(DuplicateAction[flipping]>0)
4543 {
4544 if(keypressed())
4545 {
4546 delete[] testtile;
4547 return true;
4548 }
4549
4550 duplicate=(newformat==imported_format);
4551
4552 if(duplicate)
4553 {
4554 switch(flipping)
4555 {
4556 case 0: //normal
4557 if(dest[checktile].data!=NULL)
4558 {
4559 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4560 {
4561 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4562 {
4563 // if ((dest[(checktile*128)+(y*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4564 if((dest[checktile].data[(y*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4565 {
4566 duplicate=false;
4567 }
4568 }
4569 }
4570 }
4571
4572 break;
4573
4574 case 1: //horizontal
4575 if(dest[checktile].data!=NULL)
4576 {
4577 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4578 {
4579 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4580 {
4581 // if ((dest[(checktile*128)+(y*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4582 if((dest[checktile].data[(y*8*newformat)+(14+(newformat-1)-x)/(3-newformat)])!=testtile[(y*16)+x])
4583 {
4584 duplicate=false;
4585 }
4586 }
4587 }
4588 }
4589
4590 break;
4591
4592 case 2: //vertical
4593 if(dest[checktile].data!=NULL)
4594 {
4595 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4596 {
4597 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4598 {
4599 // if ((dest[(checktile*128)+((15-y)*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4600 if((dest[checktile].data[((15-y)*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4601 {
4602 duplicate=false;
4603 }
4604 }
4605 }
4606 }
4607
4608 break;
4609
4610 case 3: //both
4611 if(dest[checktile].data!=NULL)
4612 {
4613 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4614 {
4615 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4616 {
4617 // if ((dest[(checktile*128)+((15-y)*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4618 if((dest[checktile].data[((15-y)*8*newformat)+((14+(newformat-1)-x)/(3-newformat))])!=testtile[(y*16)+x])
4619 {
4620 duplicate=false;
4621 }
4622 }
4623 }
4624 }
4625
4626 break;
4627 }
4628 }
4629
4630 if(duplicate==true)
4631 {
4632 ++duplicates_found[flipping];
4633 ++total_duplicates_found;
4634
4635 if(DuplicateAction[flipping]>1)
4636 {
4637 ++total_duplicates_discarded;
4638 temp_canadd=false;
4639 }
4640 }
4641 }
4642
4643 canadd=canadd&&temp_canadd;
4644 }
4645 }
4646 }
4647
4648 // dest[currtile].format=(cdepth==3?imported_format:cdepth);
4649 dest[currtile].format=newformat;
4650
4651 if(dest[currtile].data!=NULL)
4652 {
4653 free(dest[currtile].data);
4654 }
4655
4656 dest[currtile].data=(byte *)malloc(tilesize(dest[currtile].format));
4657
4658 if(dest[currtile].data==NULL)
4659 {
4660 Z_error_fatal("Unable to initialize tile #%d.\n", currtile);
4661 }
4662
4663 if(canadd==true)
4664 {
4665 /*
4666 for(int32_t y=0; y<16; y++)
4667 {
4668 for(int32_t x=0; x<8; x++)
4669 {
4670 dest[currtile].data[(y*8)+x]=testtile[(y*8)+x];
4671 }
4672 }
4673 */
4674 memcpy(dest[currtile].data, testtile, tilesize(dest[currtile].format));
4675 ++currtile;
4676 }
4677 }
4678 }
4679
4680 destroy_bitmap(status);
4681 delete[] testtile;
4682 return true;
4683 }
4684
4685 void grab(byte(*dest)[256],byte *def, int32_t width, int32_t height, int32_t oformat, byte *newformat)
4686 {
4687 byte defFormat=(bp==8) ? tf8Bit : tf4Bit;
4688 byte format=defFormat;
4689 int32_t stile = ((imagey*TILES_PER_ROW)+imagex)+(((sely/16)*TILES_PER_ROW)+(selx/16));
4690
4691 switch(imagetype)
4692 {
4693 case ftZGP:
4694 case ftQST:
4695 case ftZQT:
4696 case ftQSU:
4697 case ftTIL:
4698 case ftBIN:
4699 case ftBMP:
4700 for(int32_t ty=0; ty<height; ty++)
4701 {
4702 for(int32_t tx=0; tx<width; tx++)
4703 {
4704 format=defFormat;
4705 switch(imagetype)
4706 {
4707 case ftZGP:
4708 case ftQST:
4709 case ftZQT:
4710 case ftQSU:
4711 case ftTIL:
4712 format=grabtilebuf[stile+((ty*TILES_PER_ROW)+tx)].format;
4713 break;
4714 }
4715
4716 bool ever_did_unmasked = false;
4717
4718 for(int32_t y=0; y<16; y++)
4719 {
4720 for(int32_t x=0; x<16; x+=2)
4721 {
4722 bool masked = (y<8 && x<8 && grabmask&1) || (y<8 && x>7 && grabmask&2) || (y>7 && x<8 && grabmask&4) || (y>7 && x>7 && grabmask&8);
4723 if (masked)
4724 {
4725 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x)]=def[(y*16)+(x)];
4726 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x+1)]=def[(y*16)+(x+1)];
4727 }
4728 else
4729 {
4730 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x]=getpixel(screen2,(tx*16)+x+selx,(ty*16)+y+sely);
4731 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1]=getpixel(screen2,(tx*16)+x+1+selx,(ty*16)+y+sely);
4732 ever_did_unmasked = true;
4733 }
4734 if (format == tf4Bit)
4735 {
4736 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x] &= 15;
4737 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1] &= 15;
4738 }
4739 }
4740 }
4741
4742 if (ever_did_unmasked)
4743 newformat[(ty*TILES_PER_ROW)+tx] = format;
4744 }
4745 }
4746
4747 break;
4748
4749 default:
4750 for(int32_t i=0; i<200; i++)
4751 {
4752 for(int32_t j=0; j<256; j++)
4753 {
4754 dest[i][j]=0;
4755 }
4756
4757 newformat[i] = tf4Bit;
4758 }
4759
4760 break;
4761 }
4762 }
4763
4764 static void scale_imagebuf_bitmap()
4765 {
4766 imagebuf_bitmap_scale = std::clamp(imagebuf_bitmap_scale, -10, 10);
4767
4768 float scale = IMAGEBUF_SCALE;
4769 int nw = original_imagebuf_bitmap->w * scale;
4770 int nh = original_imagebuf_bitmap->h * scale;
4771 if (nw <= 0 || nh <= 0)
4772 return;
4773
4774 BITMAP* scaled_bmp = create_bitmap_ex(8, nw, nh);
4775 if (!scaled_bmp)
4776 return;
4777
4778 stretch_blit(original_imagebuf_bitmap, scaled_bmp, 0, 0, original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, 0, 0, nw, nh);
4779 if (imagebuf != original_imagebuf_bitmap)
4780 destroy_bitmap((BITMAP*)imagebuf);
4781 imagebuf = scaled_bmp;
4782 }
4783
4784 //Grabber is not grabbing to tile pages beyond pg. 252 right now. -ZX 18th June, 2019
4785 void grab_tile(int32_t tile,int32_t &cs)
4786 {
4787 zq_allow_tile_draw_cache = true;
4788
4789 int window_w = 640+6+6, window_h = 480+25+6;
4790 int window_x=(zq_screen_w-window_w)/2;
4791 int window_y=(zq_screen_h-window_h)/2;
4792 popup_zqdialog_start(window_x,window_y,window_w,window_h,-1);
4793 int window_xofs = 0;
4794 int screen_xofs=6;
4795 int screen_yofs=25;
4796 int panel_yofs=0;
4797 int bwidth = 61*1.5;
4798 int bheight = 20*1.5;
4799 int button_x = 255*2;
4800 int grab_ok_button_y = 168*2 + 32;
4801 int leech_button_x = 117*2;
4802 int leech_button_y = 166*2 + 32;
4803 int grab_cancel_button_y = 192*2 + 32;
4804 int file_button_y = 216*2 + 32;
4805 int rec_button_x = 117*2;
4806 int rec_button_y = 192*2 + 32;
4807
4808 int screen_y1 = 24;
4809 int screen_y2 = screen_y1+320-1;
4810
4811 int crect_x = 184+190;
4812 int crect_y = 168*2 + 32;
4813 int crect_w = 8*2;
4814 int crect_h = 8*2;
4815
4816 int xrect_x = 640 + 12 - 21;
4817 int xrect_y = 5;
4818
4819 byte newtile[200][256];
4820 BITMAP *screen3=create_bitmap_ex(8, zq_screen_w, zq_screen_h);
4821 clear_bitmap(screen3);
4822 byte newformat[200];
4823
4824 memset(newtile, 0, 200*256);
4825 memset(newformat, 0, 200);
4826
4827 static EXT_LIST list[] =
4828 {
4829 { (char *)"All Files (*.*)", NULL },
4830 { (char *)"Bitmap Image (*.bmp)", (char *)"bmp" },
4831 { (char *)"GIF Image (*.gif)", (char *)"gif" },
4832 { (char *)"JPEG Image (*.jpg, *.jpeg)", (char *)"jpg,jpeg" },
4833 { (char *)"ZC Tile Export (*.til)", (char *)"til" },
4834 { (char *)"ZC Quest Template (*.zqt)", (char *)"zqt" },
4835 { (char *)"ZC Quest (*.qst)", (char *)"qst" },
4836 { (char *)"ZC Graphics Pack (*.zgp)", (char *)"zgp" },
4837 { (char *)"ZC Unencoded Quest (*.qsu)", (char *)"qsu" },
4838 { (char *)"NES ROM Image (*.nes)", (char *)"nes" },
4839 { (char *)"SNES ROM Image (*.smc)", (char *)"smc" },
4840 { (char *)"Gameboy ROM Image (*.gb)", (char *)"gb" },
4841 { (char *)"Gameboy Advance ROM Image (*.gba)", (char *)"gba" },
4842 { NULL, NULL }
4843 };
4844
4845
4846 memset(cset_reduce_table, 0, 256);
4847 memset(col_diff,0,3*128);
4848 bool bdown=false;
4849 int done=0;
4850 int pal=0;
4851 int f=0;
4852 int black=vc(0),white=vc(15);
4853 int selwidth=1, selheight=1;
4854 int selx2=0, sely2=0;
4855 bool xreversed=false, yreversed=false;
4856 bool doleech=false, dofile=false, dopal=false;
4857
4858 int jwin_pal2[jcMAX];
4859 memcpy(jwin_pal2, jwin_pal, sizeof(int)*jcMAX);
4860
4861
4862 if(imagebuf==NULL)
4863 load_imagebuf();
4864
4865 calc_cset_reduce_table(imagepal, cs);
4866 calc_cset_reduce_table_8bit(imagepal);
4867 draw_grab_window();
4868 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
4869 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
4870
4871 while(gui_mouse_b())
4872 {
4873 /* do nothing */
4874 rest(1);
4875 }
4876
4877 do
4878 {
4879 HANDLE_CLOSE_ZQDLG();
4880 if(exiting_program) break;
4881 rest(4);
4882 bool redraw=false;
4883
4884 if(keypressed())
4885 {
4886 redraw=true;
4887
4888 switch(readkey()>>8)
4889 {
4890 case KEY_F:
4891 dofile=true;
4892 break;
4893
4894 case KEY_L:
4895 doleech=true;
4896 break;
4897
4898 case KEY_P:
4899 if(imagetype==ftBMP)
4900 {
4901 dopal=true;
4902 recolor=rcNone;
4903 calc_cset_reduce_table(imagepal, cs);
4904 }
4905
4906 break;
4907
4908 case KEY_ESC:
4909 done=1;
4910 break;
4911
4912 case KEY_ENTER_PAD:
4913 case KEY_ENTER:
4914 done=2;
4915 break;
4916
4917 case KEY_DOWN:
4918 if(CHECK_CTRL_CMD) sely=zc_min(sely+1,144);
4919 else ++imagey;
4920
4921 break;
4922
4923 case KEY_UP:
4924 if(CHECK_CTRL_CMD) sely=zc_max(sely-1,0);
4925 else --imagey;
4926
4927 break;
4928
4929 case KEY_RIGHT:
4930 if(CHECK_CTRL_CMD) selx=zc_min(selx+1,304);
4931 else ++imagex;
4932
4933 break;
4934
4935 case KEY_LEFT:
4936 if(CHECK_CTRL_CMD) selx=zc_max(selx-1,0);
4937 else --imagex;
4938
4939 break;
4940
4941 case KEY_PGDN:
4942 imagey+=10;
4943 break;
4944
4945 case KEY_PGUP:
4946 imagey-=10;
4947 break;
4948
4949 case KEY_HOME:
4950 imagex=imagey=0;
4951 break;
4952
4953 case KEY_EQUALS:
4954 case KEY_PLUS_PAD:
4955 cs = (cs<13) ? cs+1:0;
4956 if(recolor==rc4Bit)
4957 calc_cset_reduce_table(imagepal, cs);
4958 break;
4959
4960 case KEY_MINUS:
4961 case KEY_MINUS_PAD:
4962 cs = (cs>0) ? cs-1:13;
4963 if(recolor==rc4Bit)
4964 calc_cset_reduce_table(imagepal, cs);
4965 break;
4966
4967 case KEY_S:
4968 if(grabmode==1) grabmode=8;
4969 else if(grabmode==8) grabmode=16;
4970 else grabmode=1;
4971
4972 break;
4973
4974 case KEY_COMMA:
4975 if (imagetype == ftBMP)
4976 {
4977 imagebuf_bitmap_scale--;
4978 if (imagebuf_bitmap_scale == 0)
4979 imagebuf_bitmap_scale = -2;
4980 scale_imagebuf_bitmap();
4981 }
4982 break;
4983 case KEY_STOP:
4984 if (imagetype == ftBMP)
4985 {
4986 imagebuf_bitmap_scale++;
4987 if (imagebuf_bitmap_scale == -1)
4988 imagebuf_bitmap_scale = 1;
4989 scale_imagebuf_bitmap();
4990 }
4991 break;
4992
4993 case KEY_1:
4994 if(recolor==rc8Bit)
4995 recolor=rcNone;
4996 //imagex=(imagex*bp)>>3;
4997 bp=1;
4998 //imagex<<=3;
4999 nesmode=false;
5000 break;
5001
5002 case KEY_2:
5003 if(recolor==rc8Bit)
5004 recolor=rcNone;
5005 //imagex=(imagex*bp)>>3;
5006 bp=2;
5007 //imagex<<=2;
5008 nesmode=false;
5009 break;
5010
5011 case KEY_N:
5012 if(recolor==rc8Bit)
5013 recolor=rcNone;
5014 //imagex=(imagex*bp)>>3;
5015 bp=2;
5016 //imagex<<=2;
5017 nesmode=true;
5018 break;
5019
5020 case KEY_4:
5021 if(recolor==rc8Bit)
5022 recolor=rcNone;
5023 //imagex=(imagex*bp)>>3;
5024 bp=4;
5025 //imagex<<=1;
5026 nesmode=false;
5027 break;
5028
5029 case KEY_8:
5030 //imagex=(imagex*bp)>>3;
5031 bp=8;
5032 break;
5033
5034 case KEY_B:
5035 if(bp==2&&!nesmode)
5036 {
5037 nesmode=true;
5038 }
5039 else
5040 {
5041 nesmode=false;
5042 bp<<=1;
5043
5044 if(bp==16)
5045 {
5046 bp=1;
5047 //imagex<<=3;
5048 }
5049 else
5050 {
5051 //imagex>>=1;
5052 }
5053 }
5054
5055 break;
5056
5057 case KEY_M:
5058 romtilemode=(romtilemode+1)%4;
5059 break;
5060
5061 case KEY_Z:
5062 if(romofs>0) --romofs;
5063
5064 break;
5065
5066 case KEY_X:
5067 ++romofs;
5068 break;
5069
5070 case KEY_R:
5071 if(pal)
5072 {
5073 dopal=true;
5074 }
5075
5076 if(recolor!=rcNone)
5077 recolor=rcNone;
5078 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5079 {
5080 bp=8;
5081 recolor=rc8Bit;
5082 calc_cset_reduce_table_8bit(imagepal);
5083 }
5084 else
5085 {
5086 if(bp==8)
5087 bp=4;
5088 recolor=rc4Bit;
5089 calc_cset_reduce_table(imagepal, cs);
5090 }
5091 break;
5092
5093 default:
5094 redraw=false;
5095 }
5096
5097 clear_keybuf();
5098
5099 if(imagex<0) imagex=0;
5100
5101 if(imagey<0) imagey=0;
5102
5103 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5104 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5105 }
5106
5107 //boogie!
5108 if(gui_mouse_b()==1 && !bdown)
5109 {
5110 int x=gui_mouse_x();
5111 int y=gui_mouse_y();
5112 if(isinRect(x,y,xrect_x, xrect_y, xrect_x + 15, xrect_y + 13))
5113 if(do_x_button(screen, xrect_x, xrect_y))
5114 done=1;
5115
5116 if(!bdown)
5117 {
5118 bool regrab=false;
5119 bdown=true;
5120 FONT* oldfont = font;
5121 font = get_zc_font(font_lfont_l);
5122
5123 if(y>=screen_y1 && y<=screen_y2)
5124 {
5125 do
5126 {
5127 HANDLE_CLOSE_ZQDLG();
5128 if(exiting_program) break;
5129 int x = (gui_mouse_x()-screen_xofs) / 2;
5130 int y = (gui_mouse_y()-screen_yofs) / 2;
5131
5132 int ox=selx,oy=sely,ow=selwidth,oh=selheight;
5133
5134 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
5135 {
5136 selx=vbound((x/grabmode)*grabmode,0,304);
5137 sely=vbound((y/grabmode)*grabmode,0,144);
5138 selx2=selx;
5139 sely2=sely;
5140 selwidth=1;
5141 selheight=1;
5142 xreversed=false;
5143 yreversed=false;
5144 }
5145 else
5146 {
5147 if(xreversed)
5148 {
5149 zc_swap(selx, selx2);
5150 xreversed=false;
5151 }
5152
5153 if(yreversed)
5154 {
5155 zc_swap(sely, sely2);
5156 yreversed=false;
5157 }
5158
5159 selx2=vbound((x/grabmode)*grabmode,0,304);
5160 sely2=vbound((y/grabmode)*grabmode,0,144);
5161 selwidth=1+(abs(selx2-selx))/16;
5162 selheight=1+(abs(sely2-sely))/16;
5163
5164 if(selx2<selx)
5165 {
5166 zc_swap(selx, selx2);
5167 xreversed=true;
5168 }
5169
5170 if(sely2<sely)
5171 {
5172 zc_swap(sely, sely2);
5173 yreversed=true;
5174 }
5175 }
5176
5177 bool changed = (ox!=selx || oy!=sely || ow!=selwidth || oh!=selheight);
5178 bool redraw = changed || !(f%8);
5179
5180 if(redraw)
5181 {
5182 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5183 if(changed)
5184 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5185 if(f&8)
5186 {
5187 static const int w = 32;
5188 rect(screen,(selx*2)+screen_xofs,(sely*2)+screen_yofs,(selx*2)+screen_xofs+((selwidth-1)*w)+(w-1),(sely*2)+screen_yofs+((selheight-1)*w)+(w-1),white);
5189 }
5190 }
5191 else custom_vsync();
5192
5193 ++f;
5194 }
5195 while(gui_mouse_b());
5196 }
5197 else if(isinRect(x,y,button_x,grab_ok_button_y,button_x+bwidth,grab_ok_button_y+bheight))
5198 {
5199 if(do_text_button(button_x,grab_ok_button_y,bwidth,bheight,"OK"))
5200 done=2;
5201 }
5202 else if(isinRect(x,y,leech_button_x,leech_button_y,leech_button_x+bwidth,leech_button_y+bheight))
5203 {
5204 if(do_text_button(leech_button_x,leech_button_y,bwidth,bheight,"Leech"))
5205 {
5206 doleech=true;
5207 }
5208 }
5209 else if(isinRect(x,y,button_x,grab_cancel_button_y,button_x+bwidth,grab_cancel_button_y+bheight))
5210 {
5211 if(do_text_button(button_x,grab_cancel_button_y,bwidth,bheight,"Cancel"))
5212 done=1;
5213 }
5214 else if(isinRect(x,y,button_x,file_button_y,button_x+bwidth,file_button_y+bheight))
5215 {
5216 if(do_text_button(button_x,file_button_y,bwidth,bheight,"File"))
5217 {
5218 dofile=true;
5219 }
5220 }
5221 else if(imagetype == ftBMP && isinRect(x,y,rec_button_x, rec_button_y, rec_button_x+bwidth, rec_button_y+bheight))
5222 {
5223 if(do_text_button(rec_button_x,rec_button_y,bwidth,bheight,"Recolor"))
5224 {
5225 if(pal)
5226 {
5227 dopal = true;
5228 }
5229
5230 if(recolor!=rcNone)
5231 recolor=rcNone;
5232 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5233 {
5234 bp=8;
5235 recolor=rc8Bit;
5236 calc_cset_reduce_table_8bit(imagepal);
5237 }
5238 else
5239 {
5240 if(bp==8)
5241 bp=4;
5242 recolor=rc4Bit;
5243 calc_cset_reduce_table(imagepal, cs);
5244 }
5245 redraw=true;
5246 }
5247 }
5248 else if(isinRect(x,y+panel_yofs,crect_x,crect_y,crect_x+(16),crect_y+crect_h-1))
5249 {
5250 regrab=true;
5251 grabmask^=1;
5252 }
5253 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y,crect_x+(32)-1,crect_y+crect_h-1))
5254 {
5255 regrab=true;
5256 grabmask^=2;
5257 }
5258 else if(isinRect(x,y+panel_yofs,crect_x,crect_y+crect_h,crect_x+(16)-1,crect_y+crect_h+crect_h-1))
5259 {
5260 regrab=true;
5261 grabmask^=4;
5262 }
5263 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y+crect_h,crect_x+(32)-1,crect_y+crect_h+crect_h-1))
5264 {
5265 regrab=true;
5266 grabmask^=8;
5267 }
5268
5269 if(regrab)
5270 {
5271 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5272 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5273 redraw=true;
5274 }
5275
5276 font = oldfont;
5277 }
5278 }
5279
5280 if(gui_mouse_b()==0)
5281 bdown=false;
5282
5283 if(dofile)
5284 {
5285 if (prompt_for_existing_file_compat("Load File", "", list, imagepath, true))
5286 {
5287 zc_set_palette(RAMpal);
5288 pal=0;
5289 white=vc(15);
5290 black=vc(0);
5291 strcpy(imagepath,temppath);
5292 load_imagebuf();
5293 imagex=imagey=0;
5294 calc_cset_reduce_table(imagepal, cs);
5295 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5296 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5297 }
5298
5299 while(key[KEY_ESC])
5300 {
5301 poll_keyboard();
5302 /* do nothing */
5303 rest(1);
5304 }
5305
5306 clear_keybuf();
5307 dofile=false;
5308 redraw=true;
5309 }
5310
5311 if(doleech)
5312 {
5313 if(leech_tiles(newtilebuf,tile,cs))
5314 {
5315 done=1;
5316 }
5317 else
5318 {
5319 while(key[KEY_ESC])
5320 {
5321 poll_keyboard();
5322 /* do nothing */
5323 rest(1);
5324 }
5325
5326 clear_keybuf();
5327 redraw=true;
5328 }
5329
5330 doleech=false;
5331 }
5332
5333 if(dopal)
5334 {
5335 pal^=1;
5336
5337 if(pal)
5338 {
5339 get_bw(imagepal,black,white);
5340
5341 jwin_pal[jcBOX] =imagepal_table.data[0][jwin_pal[jcBOX]];
5342 jwin_pal[jcLIGHT] =imagepal_table.data[0][jwin_pal[jcLIGHT]];
5343 jwin_pal[jcMEDLT] =imagepal_table.data[0][jwin_pal[jcMEDLT]];
5344 jwin_pal[jcMEDDARK]=imagepal_table.data[0][jwin_pal[jcMEDDARK]];
5345 jwin_pal[jcDARK] =imagepal_table.data[0][jwin_pal[jcDARK]];
5346 jwin_pal[jcBOXFG] =imagepal_table.data[0][jwin_pal[jcBOXFG]];
5347 jwin_pal[jcTITLEL] =imagepal_table.data[0][jwin_pal[jcTITLEL]];
5348 jwin_pal[jcTITLER] =imagepal_table.data[0][jwin_pal[jcTITLER]];
5349 jwin_pal[jcTITLEFG]=imagepal_table.data[0][jwin_pal[jcTITLEFG]];
5350 jwin_pal[jcTEXTBG] =imagepal_table.data[0][jwin_pal[jcTEXTBG]];
5351 jwin_pal[jcTEXTFG] =imagepal_table.data[0][jwin_pal[jcTEXTFG]];
5352 jwin_pal[jcSELBG] =imagepal_table.data[0][jwin_pal[jcSELBG]];
5353 jwin_pal[jcSELFG] =imagepal_table.data[0][jwin_pal[jcSELFG]];
5354 gui_bg_color=jwin_pal[jcBOX];
5355 gui_fg_color=jwin_pal[jcBOXFG];
5356 jwin_set_colors(jwin_pal);
5357 }
5358 else
5359 {
5360 white=vc(15);
5361 black=vc(0);
5362
5363 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5364 gui_bg_color=jwin_pal[jcBOX];
5365 gui_fg_color=jwin_pal[jcBOXFG];
5366 jwin_set_colors(jwin_pal);
5367 }
5368
5369 zc_set_palette_range(pal?imagepal:RAMpal,0,255,false);
5370
5371 dopal=false;
5372 redraw=true;
5373 }
5374
5375 if(redraw)
5376 {
5377 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5378 }
5379 else
5380 {
5381 custom_vsync();
5382 }
5383
5384 if((f%8)==0)
5385 {
5386 stretch_blit(screen2,screen3,0, 0, zq_screen_w, zq_screen_h, 0, 0, zq_screen_w*2, zq_screen_h*2);
5387
5388 int selxl = selx* 2;
5389 int selyl = sely* 2;
5390 int w = 32;
5391
5392 if(f&8)
5393 rect(screen3,selxl,selyl,selxl+((selwidth-1)*w)+(w-1),selyl+((selheight-1)*w)+(w-1),white);
5394
5395 blit(screen3,screen,selxl,selyl,selxl+screen_xofs,selyl+screen_yofs,selwidth*w,selheight*w);
5396 }
5397
5398 // SCRFIX();
5399 ++f;
5400
5401 }
5402 while(!done);
5403
5404 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5405 gui_bg_color=jwin_pal[jcBOX];
5406 gui_fg_color=jwin_pal[jcBOXFG];
5407 jwin_set_colors(jwin_pal);
5408
5409
5410 if(done==2)
5411 {
5412 go_tiles();
5413 saved=false;
5414
5415 for(int y=0; y<selheight; y++)
5416 {
5417 for(int x=0; x<selwidth; x++)
5418 {
5419 int temptile=tile+((TILES_PER_ROW*y)+x);
5420 int format=(bp==8) ? tf8Bit : tf4Bit;
5421
5422 if(newtilebuf[temptile].data!=NULL)
5423 free(newtilebuf[temptile].data);
5424
5425 newtilebuf[temptile].format=format;
5426 newtilebuf[temptile].data=(byte *)malloc(tilesize(format));
5427
5428 if(newtilebuf[temptile].data==NULL)
5429 {
5430 Z_error_fatal("Unable to initialize tile #%d.\n", temptile);
5431 break;
5432 }
5433
5434 for(int i=0; i<256; i++)
5435 {
5436 // newtilebuf[temptile].data[i] = cset_reduce_table[newtile[(TILES_PER_ROW*y)+x][i]];
5437 newtilebuf[temptile].data[i] = newtile[(TILES_PER_ROW*y)+x][i];
5438 }
5439
5440 // unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
5441 }
5442 }
5443 }
5444
5445 destroy_bitmap(screen3);
5446
5447 if(pal)
5448 zc_set_palette(RAMpal);
5449
5450 recolor=rcNone;
5451 calc_cset_reduce_table(imagepal, cs);
5452 register_blank_tiles();
5453 popup_zqdialog_end();
5454
5455 zq_allow_tile_draw_cache = false;
5456 }
5457
5458 int32_t show_only_unused_tiles=4; //1 bit: hide used, 2 bit: hide unused, 4 bit: hide blank
5459 bool tile_is_used(int32_t tile)
5460 {
5461 return used_tile_table[tile];
5462 }
5463 void draw_tiles(int32_t first,int32_t cs, int32_t f)
5464 {
5465 draw_tiles(screen2, first, cs, f, true);
5466 }
5467 void draw_tiles(BITMAP* dest,int32_t first,int32_t cs, int32_t f, bool large, bool true_empty)
5468 {
5469 clear_bitmap(dest);
5470 BITMAP *buf = create_bitmap_ex(8,16,16);
5471
5472 int32_t w = 16;
5473 int32_t h = 16;
5474
5475 if(large)
5476 {
5477 w *=2;
5478 h *=2;
5479 }
5480
5481 for(int32_t i=0; i<TILES_PER_PAGE; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
5482 {
5483 int32_t x = (i%TILES_PER_ROW)<<4;
5484 int32_t y = (i/TILES_PER_ROW)<<4;
5485 int32_t l = 16;
5486
5487 if(large)
5488 {
5489 x*=2;
5490 y*=2;
5491 l*=2;
5492 }
5493
5494 l-=2;
5495
5496 if((HIDE_USED && tile_is_used(first+i) && !blank_tile_table[first+i]) // 1 bit: hide used
5497 || (HIDE_UNUSED && !tile_is_used(first+i) && !blank_tile_table[first+i]) // 2 bit: hide unused
5498 || (HIDE_BLANK && blank_tile_table[first+i])) // 4 bit: hide blank
5499 {
5500 if(!true_empty) //Use pure color 0; no effects
5501 {
5502 if (InvalidBG == 2)
5503 {
5504 draw_checkerboard(dest, x, y, w);
5505 }
5506 else if(InvalidBG == 1)
5507 {
5508 for(int32_t dy=0; dy<=l+1; dy++)
5509 {
5510 for(int32_t dx=0; dx<=l+1; dx++)
5511 {
5512 dest->line[dy+(y)][dx+(x)]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5513 }
5514 }
5515 }
5516 else
5517 {
5518 for(int32_t dy=0; dy<=l+1; dy++)
5519 {
5520 for(int32_t dx=0; dx<=l+1; dx++)
5521 {
5522 dest->line[dy+(y)][dx+(x)]=vc(0);
5523 }
5524 }
5525 rect(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5526 line(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5527 line(dest, (x)+1,(y)+l, (x)+l, (y)+1, vc(15));
5528 }
5529 }
5530 }
5531 else
5532 {
5533 puttile16(buf,first+i,0,0,cs,0);
5534 stretch_blit(buf,dest,0,0,16,16,x,y,w,h);
5535 }
5536
5537 if((f%32)<=16 && large && !HIDE_8BIT_MARKER && newtilebuf[first+i].format==tf8Bit)
5538 {
5539 textprintf_ex(dest,get_zc_font(font_z3smallfont),(x)+l-3,(y)+l-3,vc(int32_t((f%32)/6)+10),-1,"8");
5540 }
5541 }
5542
5543 destroy_bitmap(buf);
5544 }
5545
5546 void tile_info_0(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,bool rect_sel)
5547 {
5548 int32_t yofs=3;
5549 BITMAP *buf = create_bitmap_ex(8,16,16);
5550 int32_t mul = 2;
5551 FONT *tfont = get_zc_font(font_pfont);
5552
5553 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5554 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5555 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5556 tfont = get_zc_font(font_lfont_l);
5557
5558 // Copied tile and numbers
5559 jwin_draw_frame(screen2,(34*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5560 int32_t coldiff=TILECOL(copy)-TILECOL(copy+copycnt-1);
5561 if(copy>=0)
5562 {
5563 puttile16(buf,rect_sel&&coldiff>0?copy-coldiff:copy,0,0,cs,0);
5564 stretch_blit(buf,screen2,0,0,16,16,34*mul,216*mul+yofs,16*mul,16*mul);
5565
5566 if(copycnt>1)
5567 {
5568 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
5569 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
5570 }
5571 else
5572 {
5573 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
5574 }
5575 }
5576 else // No tiles copied
5577 {
5578 if (InvalidBG == 2)
5579 {
5580 draw_checkerboard(screen2, 34 * mul, 216 * mul + yofs, 16 * mul);
5581 }
5582 else if(InvalidBG == 1)
5583 {
5584 for(int32_t dy=0; dy<16*mul; dy++)
5585 {
5586 for(int32_t dx=0; dx<16*mul; dx++)
5587 {
5588 screen2->line[(216*mul+yofs+dy)][36*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5589 }
5590 }
5591 }
5592 else
5593 {
5594 rectfill(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(0));
5595 rect(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5596 line(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5597 line(screen2, 34*mul, ((216+15)*mul)+yofs, (34+15)*mul, (216*mul)+yofs, vc(15));
5598 }
5599 }
5600
5601
5602 // Current tile
5603 jwin_draw_frame(screen2,(104*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5604 puttile16(buf,tile,0,0,cs,0);
5605 stretch_blit(buf,screen2,0,0,16,16,104*mul,216*mul+yofs,16*mul,16*mul);
5606
5607 // Current selection mode
5608 jwin_draw_frame(screen2,(127*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5609 stretch_blit(select_bmp[rect_sel?1:0],screen2,0,0,16,16,127*mul,216*mul+yofs,16*mul,16*mul);
5610
5611 if(tile>tile2)
5612 {
5613 zc_swap(tile,tile2);
5614 }
5615
5616 char tbuf[8];
5617 tbuf[0]=0;
5618
5619 if(tile2!=tile)
5620 {
5621 sprintf(tbuf,"-%d",tile2);
5622 }
5623
5624 // Current tile and CSet text
5625 textprintf_ex(screen2,tfont,55*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cs: %d",cs);
5626 textprintf_right_ex(screen2,tfont,99*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile:");
5627 textprintf_right_ex(screen2,tfont,99*mul,224*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,tbuf);
5628
5629 FONT *tf = font;
5630 font = tfont;
5631
5632 draw_text_button(screen2,150*mul,213*mul+yofs,28*mul,21*mul,"&Grab",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5633 draw_text_button(screen2,(150+28)*mul,213*mul+yofs,28*mul,21*mul,"&Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5634 draw_text_button(screen2,(150+28*2)*mul,213*mul+yofs,28*mul,21*mul,"Export",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5635 draw_text_button(screen2,(150+28*3)*mul,213*mul+yofs,28*mul,21*mul,"Recolor",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5636 draw_text_button(screen2,(150+28*4)*mul,213*mul+yofs,28*mul,21*mul,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5637
5638 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5639 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5640 textprintf_centre_ex(screen2,tfont,(305*mul+4),220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5641 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5642
5643 font = tf;
5644
5645 int32_t w = 640;
5646 int32_t h = 480;
5647 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5648 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5649 int32_t screen_xofs=window_xofs+6;
5650 int32_t screen_yofs=window_yofs+25;
5651
5652 custom_vsync();
5653 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5654 SCRFIX();
5655 destroy_bitmap(buf);
5656 }
5657
5658 void tile_info_1(int32_t oldtile,int32_t oldflip,int32_t oldcs,int32_t tile,int32_t flip,int32_t cs,int32_t copy,int32_t page, bool always_use_flip)
5659 {
5660 int32_t yofs=3;
5661 BITMAP *buf = create_bitmap_ex(8,16,16);
5662 int32_t mul = 2;
5663 FONT *tfont = get_zc_font(font_pfont);
5664
5665 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5666 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5667 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5668 tfont = get_zc_font(font_lfont_l);
5669
5670 jwin_draw_frame(screen2,(124*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5671
5672 if(copy>=0)
5673 {
5674 puttile16(buf,copy,0,0,cs,flip);
5675 stretch_blit(buf,screen2,0,0,16,16,124*mul,216*mul+yofs,16*mul,16*mul);
5676 }
5677 else
5678 {
5679 if (InvalidBG == 2)
5680 {
5681 draw_checkerboard(screen2, 124 * mul, 216 * mul + yofs, 16 * mul);
5682 }
5683 else if(InvalidBG == 1)
5684 {
5685 for(int32_t dy=0; dy<16*mul; dy++)
5686 {
5687 for(int32_t dx=0; dx<16*mul; dx++)
5688 {
5689 screen2->line[216*mul+yofs+dy][124*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5690 }
5691 }
5692 }
5693 else
5694 {
5695 rectfill(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(0));
5696 rect(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5697 line(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5698 line(screen2, 124*mul, ((216+15)*mul)+yofs, (124+15)*mul, (216*mul)+yofs, vc(15));
5699 }
5700 }
5701
5702 jwin_draw_frame(screen2,(8*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5703 puttile16(buf,oldtile,0,0, oldcs, oldflip);
5704 stretch_blit(buf,screen2,0,0,16,16,8*mul,216*mul+yofs,16*mul,16*mul);
5705
5706 textprintf_right_ex(screen2,tfont,56*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Old Tile:");
5707 textprintf_ex(screen2,tfont,60*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldtile);
5708
5709 textprintf_right_ex(screen2,tfont,56*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5710 textprintf_ex(screen2,tfont,60*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldcs);
5711
5712 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5713 {
5714 textprintf_right_ex(screen2,tfont,56*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5715 textprintf_ex(screen2,tfont,60*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldflip);
5716 }
5717
5718 jwin_draw_frame(screen2,(148*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5719 puttile16(buf,tile,0,0, cs,
5720 (oldflip>0 || always_use_flip)?flip:0); // Suppress Flip for this usage
5721 stretch_blit(buf,screen2,0,0,16,16,148*mul,216*mul+yofs,16*mul,16*mul);
5722
5723 textprintf_right_ex(screen2,tfont,201*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"New Tile:");
5724 textprintf_ex(screen2,tfont,205*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",tile);
5725 textprintf_right_ex(screen2,tfont,201*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5726 textprintf_ex(screen2,tfont,205*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",cs);
5727
5728 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5729 {
5730 textprintf_right_ex(screen2,tfont,201*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5731 textprintf_ex(screen2,tfont,205*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",flip);
5732 }
5733
5734 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5735 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5736 textprintf_centre_ex(screen2,tfont,309*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5737 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5738
5739
5740 int32_t w = 640;
5741 int32_t h = 480;
5742 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5743 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5744 int32_t screen_xofs=window_xofs+6;
5745 int32_t screen_yofs=window_yofs+25;
5746
5747 custom_vsync();
5748 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5749 SCRFIX();
5750 destroy_bitmap(buf);
5751 }
5752 /*
5753 void reset_tile(tiledata *buf, int32_t t, int32_t format=1)
5754 {
5755 buf[t].format=format;
5756 if (buf[t].data!=NULL)
5757 {
5758 free(buf[t].data);
5759 }
5760 buf[t].data=(byte *)malloc(tilesize(buf[t].format));
5761 if (buf[t].data==NULL)
5762 {
5763 Z_error_fatal("Unable to initialize tile #%d.\n", t);
5764 }
5765 for(int32_t i=0; i<tilesize(buf[t].format); i++)
5766 {
5767 buf[t].data[i]=0;
5768 }
5769 }
5770 */
5771
5772 int32_t hide_used()
5773 {
5774 show_only_unused_tiles ^= 1;
5775 return D_O_K;
5776 }
5777 int32_t hide_unused()
5778 {
5779 show_only_unused_tiles ^= 2;
5780 return D_O_K;
5781 }
5782 int32_t hide_blank()
5783 {
5784 show_only_unused_tiles ^= 4;
5785 return D_O_K;
5786 }
5787 int32_t hide_8bit_marker()
5788 {
5789 show_only_unused_tiles ^= 8;
5790 return D_O_K;
5791 }
5792
5793 enum
5794 {
5795 MENUID_SELTILE_VIEW_HIDE_USED,
5796 MENUID_SELTILE_VIEW_HIDE_UNUSED,
5797 MENUID_SELTILE_VIEW_HIDE_BLANK,
5798 MENUID_SELTILE_VIEW_HIDE_8BIT,
5799 };
5800
1/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
12 static NewMenu select_tile_view_menu
5801 60 {
5802
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "Hide Used", hide_used, MENUID_SELTILE_VIEW_HIDE_USED },
5803
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "Hide Unused", hide_unused, MENUID_SELTILE_VIEW_HIDE_UNUSED },
5804
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "Hide Blank", hide_blank, MENUID_SELTILE_VIEW_HIDE_BLANK },
5805
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "Hide 8-bit marker", hide_8bit_marker, MENUID_SELTILE_VIEW_HIDE_8BIT },
5806 };
5807
5808 12 static std::function<void(int)> select_tile_color_depth_cb;
5809
5810 static void set_tile_color_depth_4()
5811 {
5812 select_tile_color_depth_cb(tf4Bit);
5813 }
5814 static void set_tile_color_depth_8()
5815 {
5816 select_tile_color_depth_cb(tf8Bit);
5817 }
5818 enum
5819 {
5820 MENUID_SELTILE_COLOR_DEPTH_4_BIT,
5821 MENUID_SELTILE_COLOR_DEPTH_8_BIT,
5822 };
5823
1/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
12 static NewMenu select_tile_color_depth_menu
5824 36 {
5825
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "4-bit", set_tile_color_depth_4, MENUID_SELTILE_COLOR_DEPTH_4_BIT },
5826
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "8-bit", set_tile_color_depth_8, MENUID_SELTILE_COLOR_DEPTH_8_BIT },
5827 };
5828
5829 //returns the row the tile is in on its page
5830 int32_t tile_page_row(int32_t tile)
5831 {
5832 return TILEROW(tile)-(TILEPAGE(tile)*TILE_ROWS_PER_PAGE);
5833 }
5834
5835 enum {ti_none, ti_encompass, ti_broken};
5836
5837 //striped check and striped selection
5838 int32_t move_intersection_ss(newcombo &cmb, int32_t selection_first, int32_t selection_last, int32_t offset = 0)
5839 {
5840 int32_t cmb_first = cmb.o_tile;
5841 int32_t cmb_last = cmb.o_tile;
5842 do
5843 {
5844 cmb_last = cmb.tile;
5845 animate(cmb, true);
5846 }
5847 while(cmb.tile != cmb.o_tile);
5848 reset_combo_animation(cmb);
5849 cmb_first += offset;
5850 cmb_last += offset;
5851
5852 if(cmb_first > selection_last || cmb_last < selection_first)
5853 return ti_none;
5854 if(cmb_first >= selection_first && cmb_last <= selection_last)
5855 return ti_encompass;
5856
5857 do
5858 {
5859 if(cmb.tile+offset >= selection_first && cmb.tile+offset <= selection_last)
5860 {
5861 reset_combo_animation(cmb);
5862 return ti_broken; //contained, but non-encompassing.
5863 }
5864 animate(cmb, true);
5865 }
5866 while(cmb.tile != cmb.o_tile);
5867 reset_combo_animation(cmb);
5868 return ti_none;
5869 }
5870 int32_t move_intersection_ss(int32_t check_first, int32_t check_last, int32_t selection_first, int32_t selection_last)
5871 {
5872 // if selection is before or after check...
5873 if((check_first>selection_last)||(selection_first>check_last))
5874 {
5875 return ti_none;
5876 }
5877
5878 // if selection envelopes check
5879 if((selection_first<=check_first)&&(selection_last>=check_last))
5880 {
5881 return ti_encompass; //encompass
5882 }
5883
5884 //everything else is a break
5885 return ti_broken; //intersect
5886 }
5887
5888
5889
5890 //rectangular check and striped selection
5891 int32_t move_intersection_rs(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_first, int32_t selection_last)
5892 {
5893 int32_t ret1=-1, ret2=-1;
5894
5895 for(int32_t i=0; i<check_height; ++i)
5896 {
5897 int32_t check_first=((check_top+i)*TILES_PER_ROW)+check_left;
5898 int32_t check_last=check_first+check_width-1;
5899 ret2=move_intersection_ss(check_first, check_last, selection_first, selection_last);
5900
5901 if(ret2==ti_broken)
5902 {
5903 return ti_broken;
5904 }
5905
5906 ret1=(ret2==ti_encompass?ti_encompass:ret1);
5907 }
5908
5909 if(ret1==ti_encompass)
5910 {
5911 if((TILEROW(selection_first)<=check_top) &&
5912 (TILEROW(selection_last)>=(check_top+check_height-1)))
5913 {
5914 return ti_encompass;
5915 }
5916 else
5917 {
5918 return ti_broken;
5919 }
5920 }
5921
5922 return ti_none;
5923 }
5924
5925
5926 //striped check and rectangular selection
5927 int32_t move_intersection_sr(newcombo &cmb, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height, int32_t offset = 0)
5928 {
5929 if(selection_width < TILES_PER_ROW)
5930 {
5931 int32_t cmb_first = cmb.o_tile;
5932 int32_t cmb_last = cmb.o_tile;
5933 do
5934 {
5935 cmb_last = cmb.tile;
5936 animate(cmb, true);
5937 }
5938 while(cmb.tile != cmb.o_tile);
5939 reset_combo_animation(cmb);
5940 cmb_first += offset;
5941 cmb_last += offset;
5942
5943 if((TILEROW(cmb_first)>=selection_top) &&
5944 (TILEROW(cmb_last)<=selection_top+selection_height-1) &&
5945 (TILECOL(cmb_first)>=selection_left) &&
5946 (TILECOL(cmb_last)<=TILECOL(selection_left+selection_width-1)))
5947 {
5948 return ti_encompass;
5949 }
5950 else if((cmb_last<selection_top*TILES_PER_ROW+selection_left) ||
5951 (cmb_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
5952 {
5953 return ti_none;
5954 }
5955
5956 if(TILEROW(cmb_first) == TILEROW(cmb_last))
5957 {
5958 int32_t firstcol = TILECOL(cmb_first);
5959 int32_t lastcol = TILECOL(cmb_last);
5960
5961 if(lastcol < selection_left || firstcol >= selection_left+selection_width)
5962 return ti_none;
5963 else //handle skip x
5964 {
5965 do
5966 {
5967 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width)
5968 {
5969 reset_combo_animation(cmb);
5970 return ti_broken;
5971 }
5972 animate(cmb, true);
5973 }
5974 while(cmb.tile != cmb.o_tile);
5975 reset_combo_animation(cmb);
5976 return ti_none;
5977 }
5978 }
5979 else //multi-row combo...
5980 {
5981 int32_t row = TILEROW(cmb_first);
5982
5983 do
5984 {
5985 if(row < selection_top || row > selection_top+selection_height-1)
5986 {
5987 //This row isn't in the selection; skip to next row
5988 do
5989 {
5990 animate(cmb,true);
5991 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
5992 }
5993 while(TILEROW(cmb.tile) == row);
5994 row = TILEROW(cmb.tile);
5995 continue;
5996 }
5997
5998 //This row IS in the selection; check each tile.
5999 do
6000 {
6001 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width-1)
6002 {
6003 reset_combo_animation(cmb);
6004 return ti_broken;
6005 }
6006 animate(cmb, true);
6007 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
6008 }
6009 while(TILEROW(cmb.tile) == row);
6010 row = TILEROW(cmb.tile);
6011 }
6012 while(cmb.tile != cmb.o_tile);
6013
6014 return ti_none; //...Theoretically unreachable, but if it DOES get here, it's done.
6015 }
6016 }
6017
6018 return move_intersection_ss(cmb, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1, offset);
6019 }
6020 int32_t move_intersection_sr(int32_t check_first, int32_t check_last, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
6021 {
6022 if(selection_width < TILES_PER_ROW)
6023 {
6024 if((check_last-check_first+1<=selection_width) &&
6025 (TILEROW(check_first)>=selection_top) &&
6026 (TILEROW(check_last)<=selection_top+selection_height-1) &&
6027 (TILECOL(check_first)>=selection_left) &&
6028 (TILECOL(check_last)<=TILECOL(selection_left+selection_width-1)))
6029 {
6030 return ti_encompass;
6031 }
6032 else if((check_last<selection_top*TILES_PER_ROW+selection_left) ||
6033 (check_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
6034 {
6035 return ti_none;
6036 }
6037
6038 //else if (selection_top*TILES_PER_ROW+selection_left<check_first && (selection_top+1)*TILES_PER_ROW+selection_left>check_last)
6039
6040 //one last base case: the strip we're interested in only lies along one row
6041 if(check_first/TILES_PER_ROW == check_last/TILES_PER_ROW)
6042 {
6043 int32_t cfcol = check_first%TILES_PER_ROW;
6044 int32_t clcol = check_last%TILES_PER_ROW;
6045
6046 if(clcol < selection_left || cfcol >= selection_left+selection_width)
6047 return ti_none;
6048 else
6049 return ti_broken;
6050 }
6051 else
6052 {
6053 //recursively cut the strip into substrips which lie entirely on one row
6054 int32_t currow = check_first/TILES_PER_ROW;
6055 int32_t endrow = check_last/TILES_PER_ROW;
6056 int32_t accum = 0;
6057 accum |= move_intersection_sr(check_first,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6058
6059 for(++currow; currow<endrow; currow++)
6060 {
6061 accum |= move_intersection_sr(currow*TILES_PER_ROW,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6062 }
6063
6064 accum |= move_intersection_sr(currow*TILES_PER_ROW, check_last,selection_left,selection_top,selection_width,selection_height);
6065
6066 if(accum > 0)
6067 return ti_broken;
6068
6069 return ti_none;
6070 }
6071 }
6072
6073 return move_intersection_ss(check_first, check_last, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1);
6074 }
6075
6076 //rectangular check and rectangular selection
6077 int32_t move_intersection_rr(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
6078 {
6079 if((check_left>=selection_left) &&
6080 (check_left+check_width<=selection_left+selection_width) &&
6081 (check_top>=selection_top) &&
6082 (check_top+check_height<=selection_top+selection_height))
6083 {
6084 return ti_encompass;
6085 }
6086 else
6087 {
6088 for(int32_t i=check_top; i<check_top+check_height; ++i)
6089 {
6090 if(move_intersection_rs(selection_left, selection_top, selection_width, selection_height, i*TILES_PER_ROW+check_left, i*TILES_PER_ROW+check_left+check_width-1)!=ti_none)
6091 {
6092 return ti_broken;
6093 }
6094 }
6095 }
6096
6097 return ti_none;
6098 }
6099
6100
6101
6102
6103 static DIALOG move_textbox_list_dlg[] =
6104 {
6105 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
6106 12 { jwin_win_proc, 0, 0, 300, 212, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6107 12 { jwin_ctext_proc, 150, 18, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6108 12 { jwin_ctext_proc, 150, 28, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6109 12 { jwin_textbox_proc, 12, 40, 277, 138, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6110 12 { jwin_button_proc, 80, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
6111 12 { jwin_button_proc, 160, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
6112 12 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
6113 12 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
6114 };
6115
6116 bool popup_move_textbox_dlg(string const& msg, char* textbox, char const* title)
6117 {
6118 char buf1[512] = {0};
6119 char buf2[512] = {0};
6120 large_dialog(move_textbox_list_dlg);
6121 DIALOG& tbox = move_textbox_list_dlg[3];
6122 {
6123 FONT* f = tbox.dp2 ? (FONT*)tbox.dp2 : get_custom_font(CFONT_GUI);
6124 int indx = 0, word_indx = 0;
6125 for(char c : msg)
6126 {
6127 if(c == ' ' || c == '\n')
6128 word_indx = indx;
6129 buf1[indx++] = c;
6130 if(c == '\n' || text_length(f, buf1) >= tbox.w)
6131 {
6132 buf1[word_indx] = 0;
6133 strcpy(buf2, msg.c_str()+word_indx+1);
6134 break;
6135 }
6136 }
6137 }
6138
6139 move_textbox_list_dlg[0].dp = (void*)title;
6140 move_textbox_list_dlg[0].dp2 = get_zc_font(font_lfont);
6141 move_textbox_list_dlg[1].dp = buf1;
6142 move_textbox_list_dlg[2].dp = buf2;
6143 tbox.dp = textbox;
6144 tbox.d2 = 0;
6145 auto tby = tbox.y;
6146 auto tbh = tbox.h;
6147 if(!buf2[0])
6148 {
6149 auto diff = move_textbox_list_dlg[2].h;
6150 tbox.y -= diff;
6151 tbox.h += diff;
6152 }
6153
6154 int32_t ret=do_zqdialog(move_textbox_list_dlg,2);
6155 position_mouse_z(0);
6156 tbox.y = tby;
6157 tbox.h = tbh;
6158
6159 return ret == 4;
6160 }
6161
6162 int32_t quick_select_3(int32_t a, int32_t b, int32_t c, int32_t d)
6163 {
6164 return a==0?b:a==1?c:d;
6165 }
6166
6167 bool TileMoveList::process(std::unique_ptr<BaseTileRef>& ref, TileMoveProcess const& proc, bool is_dest)
6168 {
6169 TileRefCombo* combo_ref = dynamic_cast<TileRefCombo*>(ref.get());
6170 int i = ti_none;
6171 auto t = ref->getTile() + ref->offset();
6172
6173 if(combo_ref)
6174 {
6175 if(proc.rect)
6176 i=move_intersection_sr(*combo_ref->combo, proc._l, proc._t, proc._w, proc._h);
6177 else i=move_intersection_ss(*combo_ref->combo, proc._first, proc._last);
6178 }
6179 else if(proc.rect)
6180 {
6181 if(ref->h > 1)
6182 i=move_intersection_rr(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._l, proc._t, proc._w, proc._h);
6183 else i=move_intersection_sr(t, t+ref->w-1, proc._l, proc._t, proc._w, proc._h);
6184 }
6185 else
6186 {
6187 if(ref->h > 1)
6188 i=move_intersection_rs(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._first, proc._last);
6189 else i=move_intersection_ss(t, t+ref->w-1, proc._first, proc._last);
6190 }
6191
6192 bool in = i != ti_none, out = i != ti_encompass;
6193 for(size_t q = 0; !(in&&out) && q < ref->extra_rects.size(); ++q)
6194 {
6195 auto [ex_t,ex_w,ex_h] = ref->extra_rects[q];
6196 if(proc.rect)
6197 i = move_intersection_rr(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._l, proc._t, proc._w, proc._h);
6198 else i = move_intersection_rs(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._first, proc._last);
6199 if(i != ti_none)
6200 in = true;
6201 if(i != ti_encompass)
6202 out = true;
6203 }
6204 i = in ? (out ? ti_broken : ti_encompass) : ti_none;
6205
6206 if(i != ti_none && ref->getTile() != 0)
6207 {
6208 if(mode == Mode::CHECK_ALL)
6209 {
6210 move_refs.emplace_back(std::move(ref));
6211 return true;
6212 }
6213 else if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6214 {
6215 if(warning_flood || warning_list.tellp() >= 65000)
6216 {
6217 if(!warning_flood)
6218 warning_list << "...\n...\n...\nmany others";
6219 warning_flood = true;
6220 }
6221 else
6222 warning_list << ref->name << '\n';
6223 }
6224 else if(i==ti_encompass)
6225 {
6226 move_refs.emplace_back(std::move(ref));
6227 return true;
6228 }
6229 }
6230 return false;
6231 }
6232
6233 bool TileMoveList::check_prot()
6234 {
6235 if(!TileProtection)
6236 return true;
6237 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Tile Warning");
6238
6239 warning_flood = false;
6240 warning_list.clear();
6241
6242 return ret;
6243 }
6244
6245 void TileMoveList::add_diff(int diff)
6246 {
6247 for(auto& ref : move_refs)
6248 ref->addTile(diff);
6249 }
6250
6251 //from 'combo.h'
6252 bool ComboMoveList::process(std::unique_ptr<BaseComboRef>& ref, ComboMoveProcess const& proc, bool is_dest)
6253 {
6254 int i = ti_none;
6255 auto c = ref->getCombo();
6256
6257 if(ref->no_move)
6258 processed_combos[c] = true;
6259 else processed_combos[c]; //inserts element if does not exist
6260 i = move_intersection_ss(c, c, proc._first, proc._last);
6261
6262 if(i != ti_none && ref->getCombo() != 0)
6263 {
6264 if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6265 {
6266 if(ComboProtection)
6267 {
6268 if(warning_flood || warning_list.tellp() >= 65000)
6269 {
6270 if(!warning_flood)
6271 warning_list << "...\n...\n...\nmany others";
6272 warning_flood = true;
6273 }
6274 else
6275 warning_list << ref->name << '\n';
6276 }
6277 }
6278 else if(i==ti_encompass)
6279 {
6280 move_refs.emplace_back(std::move(ref));
6281 return true;
6282 }
6283 }
6284 return false;
6285 }
6286
6287 bool ComboMoveList::check_prot()
6288 {
6289 if(!ComboProtection)
6290 return true;
6291 vector<set<int> const*> subset = combo_links.subset(processed_combos);
6292 bool subset_header = false;
6293 for(int q = 0; q < 2; ++q)
6294 {
6295 bool is_dest = (q==1);
6296 if(!is_dest && !source_process)
6297 continue;
6298 ComboMoveProcess const& proc = is_dest ? dest_process : *source_process;
6299 for(auto it = subset.begin(); it != subset.end();)
6300 {
6301 auto s = *it;
6302 if(warning_flood || warning_list.tellp() >= 65000)
6303 {
6304 if(!warning_flood)
6305 warning_list << "...\n...\n...\nmany others";
6306 warning_flood = true;
6307 break;
6308 }
6309 set<int> in_set, out_set;
6310 bool no_move = is_dest;
6311 for(int c : *s)
6312 {
6313 int i = move_intersection_ss(c, c, proc._first, proc._last);
6314 if(i != ti_none)
6315 in_set.insert(c);
6316 if(i != ti_encompass)
6317 out_set.insert(c);
6318 if(!no_move)
6319 {
6320 auto it = processed_combos.find(c);
6321 if(it != processed_combos.end() && it->second)
6322 no_move = true;
6323 }
6324 }
6325 int i = in_set.empty() ? ti_none : (out_set.empty() ? ti_encompass : ti_broken);
6326 if(i == ti_encompass && !no_move)
6327 {
6328 it = subset.erase(it);
6329 continue;
6330 }
6331 if(i == ti_none)
6332 {
6333 ++it;
6334 continue;
6335 }
6336
6337 if(!subset_header)
6338 {
6339 subset_header = true;
6340 warning_list << "===== Broken Relative Combo Groups =====\n";
6341 }
6342 bool comma = false;
6343 warning_list << "In(";
6344 for(int c : in_set)
6345 {
6346 if(comma)
6347 warning_list << ",";
6348 else comma = true;
6349 warning_list << c;
6350 }
6351 warning_list << "),Out(";
6352 comma = false;
6353 for(int c : out_set)
6354 {
6355 if(comma)
6356 warning_list << ",";
6357 else comma = true;
6358 warning_list << c;
6359 }
6360 warning_list << ")\n";
6361 it = subset.erase(it);
6362 }
6363 }
6364 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Combo Warning");
6365
6366 processed_combos.clear();
6367 warning_flood = false;
6368 warning_list.clear();
6369
6370 return ret;
6371 }
6372
6373 void ComboMoveList::add_diff(int diff)
6374 {
6375 for(auto& ref : move_refs)
6376 ref->addCombo(diff);
6377 }
6378
6379 static void collect_subscreen_tiles(SubscrWidget& widget, TileMoveList& list)
6380 {
6381 if (auto w = dynamic_cast<SW_2x2Frame*>(&widget))
6382 {
6383 list.add_tile(&w->tile, 2, 2, "2x2 Frame");
6384 }
6385 else if (auto w = dynamic_cast<SW_TriFrame*>(&widget))
6386 {
6387 list.add_tile(&w->frame_tile, 6, 3, "McGuffin Frame - Frame");
6388 list.add_tile(&w->piece_tile, "McGuffin Frame - Piece");
6389 }
6390 else if (auto w = dynamic_cast<SW_McGuffin*>(&widget))
6391 {
6392 list.add_tile(&w->tile, "McGuffin Piece");
6393 }
6394 else if (auto w = dynamic_cast<SW_TileBlock*>(&widget))
6395 {
6396 list.add_tile(&w->tile, w->w, w->h, "TileBlock");
6397 }
6398 else if (auto w = dynamic_cast<SW_MiniTile*>(&widget))
6399 {
6400 if (w->tile == -1)
6401 return;
6402
6403 list.add_tile(&w->tile, "MiniTile");
6404 }
6405 else if (auto w = dynamic_cast<SW_GaugePiece*>(&widget))
6406 {
6407 int fr = w->frames ? w->frames : 1;
6408 fr = fr * (1+(w->get_per_container()/(w->unit_per_frame+1)));
6409 if(!(w->flags&SUBSCR_GAUGE_FULLTILE))
6410 fr = (fr/4_zf).getCeil();
6411
6412 for(auto q = 0; q < 4; ++q)
6413 {
6414 list.add_tile(&w->mts[q].mt_tile, fr, 1, fmt::format("Gauge Tile {}", q));
6415 }
6416 }
6417 }
6418
6419 static void collect_subscreen_tiles(SubscrPage& page, TileMoveList& list)
6420 {
6421 for(auto q = 0; q < page.contents.size(); ++q)
6422 {
6423 size_t indx = list.move_refs.size();
6424 collect_subscreen_tiles(*page.contents[q], list);
6425 for(; indx < list.move_refs.size(); ++indx)
6426 {
6427 auto& ref = list.move_refs[indx];
6428 ref->name = fmt::format("Widget {} - {}", q, ref->name);
6429 }
6430 }
6431 }
6432
6433 static void collect_subscreen_tiles(ZCSubscreen& subscreen, TileMoveList& list)
6434 {
6435 for (auto q = 0; q < subscreen.pages.size(); ++q)
6436 {
6437 size_t indx = list.move_refs.size();
6438 collect_subscreen_tiles(subscreen.pages[q], list);
6439 for(; indx < list.move_refs.size(); ++indx)
6440 {
6441 auto& ref = list.move_refs[indx];
6442 ref->name = fmt::format("Page {} - {}", q, ref->name);
6443 }
6444 }
6445 }
6446
6447 bool _handle_tile_move(TileMoveProcess dest_process, optional<TileMoveProcess> source_process, int diff, TileMoveUndo* on_undo = nullptr, std::function<void(int32_t)> every_proc = nullptr, TileMoveList::Mode mode = TileMoveList::Mode::MOVE)
6448 {
6449 bool BSZ2 = get_qr(qr_BSZELDA);
6450 bool move = source_process.has_value();
6451 TileMoveUndo local_undo;
6452 TileMoveUndo& storage = on_undo ? *on_undo : local_undo;
6453 auto& vec = storage.vec;
6454 storage.diff = diff;
6455 storage.state = false;
6456
6457 //Combos
6458 {
6459 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6460 dest_process, source_process, mode,
6461 move
6462 ? "The tiles used by the following combos will be partially cleared by the move."
6463 : "The tiles used by the following combos will be partially or completely overwritten by this process."
6464 ));
6465 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6466 {
6467 auto& cmb = combobuf[q];
6468 auto lbl = fmt::format("Combo {}{}", q, cmb.label.empty() ? ""
6469 : fmt::format(" ({})", cmb.label));
6470 movelist->add_combo(&cmb, lbl);
6471
6472 //type-specific
6473 char const* type_name = ZI.getComboTypeName(cmb.type);
6474 switch(cmb.type)
6475 {
6476 case cSPOTLIGHT:
6477 {
6478 if(!(cmb.usrflags & cflag1))
6479 break;
6480 movelist->add_tile_10k(&cmb.attributes[0], 16, 1, fmt::format("{} - Type '{}' - Beam Tiles", lbl, type_name));
6481 break;
6482 }
6483 }
6484 }
6485 if(!every_proc && !movelist->check_prot())
6486 return false;
6487 }
6488 //Items
6489 {
6490 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6491 dest_process, source_process, mode,
6492 move
6493 ? "The tiles used by the following items will be partially cleared by the move."
6494 : "The tiles used by the following items will be partially or completely overwritten by this process."
6495 ));
6496 build_bii_list(false);
6497 for(int32_t u=0; u<MAXITEMS; u++)
6498 {
6499 auto id = bii[u].i;
6500 itemdata& itm = itemsbuf[id];
6501 if(itm.type == itype_bottle)
6502 {
6503 vector<std::tuple<int,int,int>> rects;
6504 auto fr = itm.frames;
6505 for(int q = 0; q < NUM_BOTTLE_TYPES; ++q)
6506 {
6507 bottletype const& bt = QMisc.bottle_types[q];
6508 if(bt.is_blank())
6509 continue;
6510 rects.emplace_back(fr+q*fr, fr, 1);
6511 }
6512 movelist->add_tile(&itm.tile, fr, 1, fmt::format("Item {}", id),
6513 false, 0, 0, rects);
6514 }
6515 else movelist->add_tile(&itm.tile, itm.frames, 1, fmt::format("Item {}", id));
6516 }
6517 if(!every_proc && !movelist->check_prot())
6518 return false;
6519 }
6520 //Weapon sprites
6521 {
6522 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6523 dest_process, source_process, mode,
6524 move
6525 ? "The tiles used by the following weapons will be partially cleared by the move."
6526 : "The tiles used by the following weapons will be partially or completely overwritten by this process."
6527 ));
6528 build_biw_list();
6529
6530 for(int32_t u=0; u<MAXWPNS; u++)
6531 {
6532 bool ignore_frames=false;
6533 int32_t m=0;
6534
6535 auto id = biw[u].i;
6536 auto& wpn = wpnsbuf[id];
6537
6538 switch(biw[u].i)
6539 {
6540 case wSWORD:
6541 case wWSWORD:
6542 case wMSWORD:
6543 case wXSWORD:
6544 m=3+((wpnsbuf[biw[u].i].type==3)?1:0);
6545 break;
6546
6547 case wSWORDSLASH:
6548 case wWSWORDSLASH:
6549 case wMSWORDSLASH:
6550 case wXSWORDSLASH:
6551 m=4;
6552 break;
6553
6554 case iwMMeter:
6555 m=9;
6556 break;
6557
6558 case wBRANG:
6559 case wMBRANG:
6560 case wFBRANG:
6561 m=BSZ2?1:3;
6562 break;
6563
6564 case wBOOM:
6565 case wSBOOM:
6566 case ewBOOM:
6567 case ewSBOOM:
6568 ignore_frames=true;
6569 m=2;
6570 break;
6571
6572 case wWAND:
6573 m=1;
6574 break;
6575
6576 case wMAGIC:
6577 m=1;
6578 break;
6579
6580 case wARROW:
6581 case wSARROW:
6582 case wGARROW:
6583 case ewARROW:
6584 m=1;
6585 break;
6586
6587 case wHAMMER:
6588 m=8;
6589 break;
6590
6591 case wHSHEAD:
6592 m=1;
6593 break;
6594
6595 case wHSCHAIN_H:
6596 m=1;
6597 break;
6598
6599 case wHSCHAIN_V:
6600 m=1;
6601 break;
6602
6603 case wHSHANDLE:
6604 m=1;
6605 break;
6606
6607 case iwDeath:
6608 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6609 {
6610 ignore_frames = true;
6611 m=BSZ2?4:2;
6612 }
6613 break;
6614
6615 case iwSpawn:
6616 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6617 {
6618 ignore_frames = true;
6619 m=3;
6620 }
6621 break;
6622 }
6623
6624 movelist->add_tile(&wpn.tile, zc_max((ignore_frames?0:wpn.frames),1)+m,
6625 1, fmt::format("{} {}", biw[u].s, id));
6626
6627 //Tile 54+55 are "Impact (not shown in sprite list)", for u==3 "Arrow" and u==9 "Boomerang"
6628 //...these can't be updated by a move.
6629 if((u==3)||(u==9))
6630 {
6631 static int32_t impact_tiles[2] = {54,54};
6632 auto& tile = impact_tiles[u==3 ? 0 : 1];
6633 tile = 54; //dummy tile, ensure it's correct
6634 movelist->add_tile(&tile, 2, 1,
6635 fmt::format("{} Impact (not shown in sprite list)",(u==3)?"Arrow":"Boomerang"),
6636 true);
6637 }
6638 }
6639 if(!every_proc && !movelist->check_prot())
6640 return false;
6641 }
6642 //Hero sprites
6643 {
6644 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6645 dest_process, source_process, mode,
6646 move
6647 ? "The tiles used by the following Hero sprites will be partially cleared by the move."
6648 : "The tiles used by the following Hero sprites will be partially or completely overwritten by this process."
6649 ));
6650 {
6651 int32_t a_style=(zinit.heroAnimationStyle);
6652 #define ADD_HERO_SPRITE(ref_sprite, frames, name) \
6653 do \
6654 { \
6655 movelist->add_tile(&ref_sprite[spr_tile], \
6656 (ref_sprite[spr_extend] < 2 ? 1 : 2) * frames, \
6657 ref_sprite[spr_extend] < 1 ? 1 : 2, \
6658 name, false, \
6659 ref_sprite[spr_extend] < 2 ? 0 : -1, \
6660 ref_sprite[spr_extend] < 1 ? 0 : -1); \
6661 } while(false)
6662 // + (ref_sprite[spr_extend] < 2 ? 0 : 1) //this was on some of the 'width's before... but doesn't make sense?
6663
6664 for(int32_t i=0; i<4; ++i)
6665 {
6666 ADD_HERO_SPRITE(walkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Walking ({})", dirstr_proper[i]));
6667 }
6668
6669 for(int32_t i=0; i<4; ++i)
6670 {
6671 ADD_HERO_SPRITE(slashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slashing ({})", dirstr_proper[i]));
6672 }
6673
6674 for(int32_t i=0; i<4; ++i)
6675 {
6676 ADD_HERO_SPRITE(stabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Stabbing ({})", dirstr_proper[i]));
6677 }
6678
6679 for(int32_t i=0; i<4; ++i)
6680 {
6681 ADD_HERO_SPRITE(poundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Pounding ({})", dirstr_proper[i]));
6682 }
6683
6684 for(int32_t i=0; i<2; ++i)
6685 {
6686 ADD_HERO_SPRITE(holdspr[0][i], 1, fmt::format("Hold (Land, {}-hand)", i+1));
6687 }
6688
6689 ADD_HERO_SPRITE(castingspr, 1, "Casting");
6690
6691 for(int32_t i=0; i<4; ++i)
6692 {
6693 ADD_HERO_SPRITE(floatspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Floating ({})", dirstr_proper[i]));
6694 }
6695
6696 for(int32_t i=0; i<4; ++i)
6697 {
6698 ADD_HERO_SPRITE(swimspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Swimming ({})", dirstr_proper[i]));
6699 }
6700
6701 for(int32_t i=0; i<4; ++i)
6702 {
6703 ADD_HERO_SPRITE(divespr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Diving ({})", dirstr_proper[i]));
6704 }
6705
6706 for(int32_t i=0; i<2; ++i)
6707 {
6708 ADD_HERO_SPRITE(holdspr[1][i], 1, fmt::format("Hold (Water, {}-hand)", i));
6709 }
6710
6711 for(int32_t i=0; i<4; ++i)
6712 {
6713 ADD_HERO_SPRITE(jumpspr[i], 3, fmt::format("Jumping ({})", dirstr_proper[i]));
6714 }
6715
6716 for(int32_t i=0; i<4; ++i)
6717 {
6718 ADD_HERO_SPRITE(chargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Charging ({})", dirstr_proper[i]));
6719 }
6720 for(int32_t i=0; i<4; ++i)
6721 {
6722 ADD_HERO_SPRITE(revslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slash 2 ({})", dirstr_proper[i]));
6723 }
6724 for(int32_t i=0; i<4; ++i)
6725 {
6726 ADD_HERO_SPRITE(fallingspr[i], 7, fmt::format("Falling ({})", dirstr_proper[i]));
6727 }
6728 for(int32_t i=0; i<4; ++i)
6729 {
6730 ADD_HERO_SPRITE(liftingspr[i], liftingspr[i][spr_frames], fmt::format("Lifting ({})", dirstr_proper[i]));
6731 }
6732 for(int32_t i=0; i<4; ++i)
6733 {
6734 ADD_HERO_SPRITE(liftingwalkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Lift-Walking ({})", dirstr_proper[i]));
6735 }
6736 for(int32_t i=0; i<4; ++i)
6737 {
6738 ADD_HERO_SPRITE(drowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Drowning ({})", dirstr_proper[i]));
6739 }
6740 for(int32_t i=0; i<4; ++i)
6741 {
6742 ADD_HERO_SPRITE(drowning_lavaspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Lava Drowning ({})", dirstr_proper[i]));
6743 }
6744 for(int32_t i=0; i<4; ++i)
6745 {
6746 ADD_HERO_SPRITE(sideswimspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swimming ({})", dirstr_proper[i]));
6747 }
6748 //69
6749 for(int32_t i=0; i<4; ++i)
6750 {
6751 ADD_HERO_SPRITE(sideswimslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Side-Swim Slash ({})", dirstr_proper[i]));
6752 }
6753 //73
6754 for(int32_t i=0; i<4; ++i)
6755 {
6756 ADD_HERO_SPRITE(sideswimstabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Stab ({})", dirstr_proper[i]));
6757 }
6758 //77
6759 for(int32_t i=0; i<4; ++i)
6760 {
6761 ADD_HERO_SPRITE(sideswimpoundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Pound ({})", dirstr_proper[i]));
6762 }
6763 //81
6764 for(int32_t i=0; i<4; ++i)
6765 {
6766 ADD_HERO_SPRITE(sideswimchargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Side-Swim Charging ({})", dirstr_proper[i]));
6767 }
6768 //85
6769 ADD_HERO_SPRITE(sideswimholdspr[spr_hold1], 1, "Hold (Side-Water, 1-hand)");
6770 ADD_HERO_SPRITE(sideswimholdspr[spr_hold2], 1, "Hold (Side-Water, 2-hand)");
6771 ADD_HERO_SPRITE(sideswimcastingspr, 1, "Side-Swim Casting");
6772 for(int32_t i=0; i<4; ++i)
6773 {
6774 ADD_HERO_SPRITE(sidedrowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swim Drowning ({})", dirstr_proper[i]));
6775 }
6776 //91
6777 }
6778 if(!every_proc && !movelist->check_prot())
6779 return false;
6780 }
6781 //Map Styles
6782 {
6783 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6784 dest_process, source_process, mode,
6785 move
6786 ? "The tiles used by the following map styles will be partially cleared by the move."
6787 : "The tiles used by the following map styles will be partially or completely overwritten by this process."
6788 ));
6789 movelist->add_tile(&QMisc.colors.blueframe_tile, 2, 2, "Frame");
6790 movelist->add_tile(&QMisc.colors.HCpieces_tile, zinit.hcp_per_hc, 1, "Heart Container Piece");
6791 movelist->add_tile(&QMisc.colors.triforce_tile, BSZ2?2:1, BSZ2?3:1, "McGuffin Fragment");
6792 movelist->add_tile(&QMisc.colors.triframe_tile, BSZ2?7:6, BSZ2?7:3, "McGuffin Frame");
6793 movelist->add_tile(&QMisc.colors.overworld_map_tile, 5, 3, "Overworld Map");
6794 movelist->add_tile(&QMisc.colors.dungeon_map_tile, 5, 3, "Dungeon Map");
6795 if(!every_proc && !movelist->check_prot())
6796 return false;
6797 }
6798 //Game Icons
6799 {
6800 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6801 dest_process, source_process, mode,
6802 move
6803 ? "The tiles used by the following game icons will be partially cleared by the move."
6804 : "The tiles used by the following game icons will be partially or completely overwritten by this process."
6805 ));
6806 for(int32_t u=0; u<4; u++)
6807 movelist->add_tile(&QMisc.icons[u], fmt::format("Game Icon {}", u));
6808 if(!every_proc && !movelist->check_prot())
6809 return false;
6810 }
6811 //DMaps
6812 {
6813 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6814 dest_process, source_process, mode,
6815 move
6816 ? "The tiles used by the following dmaps will be partially cleared by the move."
6817 : "The tiles used by the following dmaps will be partially or completely overwritten by this process."
6818 ));
6819 for(int32_t u=0; u<MAXDMAPS; u++)
6820 {
6821 auto& dm = DMaps[u];
6822 movelist->add_tile(&dm.minimap_tile[0], 5, 3, fmt::format("DMap {} - Minimap (Empty)", u));
6823 movelist->add_tile(&dm.minimap_tile[1], 5, 3, fmt::format("DMap {} - Minimap (Filled)", u));
6824 movelist->add_tile(&dm.largemap_tile[0], BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Empty)", u));
6825 movelist->add_tile(&dm.largemap_tile[1], BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Filled)", u));
6826 }
6827 if(!every_proc && !movelist->check_prot())
6828 return false;
6829 }
6830 //Enemies
6831 {
6832 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6833 dest_process, source_process, mode,
6834 move
6835 ? "The tiles used by the following enemies will be partially cleared by the move."
6836 : "The tiles used by the following enemies will be partially or completely overwritten by this process."
6837 ));
6838 build_bie_list(false);
6839 bool newtiles=get_qr(qr_NEWENEMYTILES)!=0;
6840 for(int u=0; u<eMAXGUYS; u++)
6841 {
6842 guydata& enemy=guysbuf[bie[u].i];
6843 bool darknut=false;
6844 bool gleeok=false;
6845
6846 if(enemy.type==eeWALK && ((enemy.flags&(guy_shield_back|guy_shield_front|guy_shield_left|guy_shield_right))!=0))
6847 darknut=true;
6848 else if(enemy.type==eeGLEEOK)
6849 gleeok=true;
6850 else if (enemy.type == eePATRA)
6851 {
6852 if (!get_qr(qr_PATRAS_USE_HARDCODED_OFFSETS))
6853 {
6854 darknut=true; //uses the same logic no need for separate variables!
6855 }
6856 }
6857
6858 // Dummied out enemies
6859 if(bie[u].i>=eOCTO1S && bie[u].i<e177)
6860 {
6861 if(old_guy_string[bie[u].i][strlen(old_guy_string[bie[u].i])-1]==' ')
6862 {
6863 continue;
6864 }
6865 }
6866
6867 if(newtiles)
6868 {
6869 if(enemy.e_tile==0)
6870 {
6871 continue;
6872 }
6873
6874 vector<std::tuple<int,int,int>> rects;
6875
6876 if(darknut) //or anything that uses S. Tile for with new tiles
6877 {
6878 if (enemy.s_tile != 0)
6879 {
6880 movelist->add_tile(&enemy.s_tile, enemy.s_width, enemy.s_height, fmt::format("Enemy {} ({}) 'Special'", u, bie[u].s));
6881 }
6882 }
6883 else if (gleeok)
6884 {
6885 for (int32_t j = 0; j < enemy.attributes[4]; ++j)
6886 {
6887 rects.emplace_back(enemy.attributes[5] + (enemy.attributes[6]*j), 4, 1);
6888 }
6889 rects.emplace_back(enemy.attributes[7], 4, 1);
6890 rects.emplace_back(enemy.attributes[8], 4, 1);
6891 }
6892 movelist->add_tile(&enemy.e_tile, enemy.e_width, enemy.e_height, fmt::format("Enemy {} ({}) 'New'", u, bie[u].s),
6893 false, 0, 0, rects);
6894
6895 }
6896 else
6897 {
6898 if(enemy.tile==0)
6899 {
6900 continue;
6901 }
6902 movelist->add_tile(&enemy.tile, enemy.width, enemy.height, fmt::format("Enemy {} ({}) 'Old'", u, bie[u].s));
6903
6904 if(enemy.s_tile!=0)
6905 {
6906 movelist->add_tile(&enemy.s_tile, enemy.s_width, enemy.s_height, fmt::format("Enemy {} ({}) 'Special'", u, bie[u].s));
6907 }
6908 }
6909 }
6910 if(!every_proc && !movelist->check_prot())
6911 return false;
6912 }
6913 //Subscreens
6914 {
6915 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6916 dest_process, source_process, mode,
6917 move
6918 ? "The tiles used by the following subscreen widgets will be partially cleared by the move."
6919 : "The tiles used by the following subscreen widgets will be partially or completely overwritten by this process."
6920 ));
6921
6922 for(auto q = 0; q < subscreens_active.size(); ++q)
6923 {
6924 size_t indx = movelist->move_refs.size();
6925 collect_subscreen_tiles(subscreens_active[q], *movelist.get());
6926 for(; indx < movelist->move_refs.size(); ++indx)
6927 {
6928 auto& ref = movelist->move_refs[indx];
6929 ref->name = fmt::format("Active Subscr {} - {}", q, ref->name);
6930 }
6931 }
6932 for(auto q = 0; q < subscreens_passive.size(); ++q)
6933 {
6934 size_t indx = movelist->move_refs.size();
6935 collect_subscreen_tiles(subscreens_passive[q], *movelist.get());
6936 for(; indx < movelist->move_refs.size(); ++indx)
6937 {
6938 auto& ref = movelist->move_refs[indx];
6939 ref->name = fmt::format("Passive Subscr {} - {}", q, ref->name);
6940 }
6941 }
6942 for(auto q = 0; q < subscreens_overlay.size(); ++q)
6943 {
6944 size_t indx = movelist->move_refs.size();
6945 collect_subscreen_tiles(subscreens_overlay[q], *movelist.get());
6946 for(; indx < movelist->move_refs.size(); ++indx)
6947 {
6948 auto& ref = movelist->move_refs[indx];
6949 ref->name = fmt::format("Overlay Subscr {} - {}", q, ref->name);
6950 }
6951 }
6952 if(!every_proc && !movelist->check_prot())
6953 return false;
6954 }
6955 //Strings
6956 {
6957 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6958 dest_process, source_process, mode,
6959 move
6960 ? "The tiles used by the following strings will be partially cleared by the move."
6961 : "The tiles used by the following strings will be partially or completely overwritten by this process."
6962 ));
6963 for(size_t q = 0; q < msg_count; ++q)
6964 {
6965 MsgStr& str = MsgStrings[q];
6966 std::string text = str.serialize();
6967 bool fulltile = str.stringflags & STRINGFLAG_FULLTILE;
6968 movelist->add_tile(&str.tile, fulltile ? (str.w/16_zf).getCeil() : 2,
6969 fulltile ? (str.h/16_zf).getCeil() : 2, fmt::format("{} (BG): '{}'", q, util::snip(text,100)));
6970 movelist->add_tile(&str.portrait_tile, str.portrait_tw, str.portrait_th,
6971 fmt::format("{} (Port.): '{}'", q, util::snip(text,100)));
6972 }
6973 if(!every_proc && !movelist->check_prot())
6974 return false;
6975 }
6976
6977 if(source_process) //Apply the 'diff' value to all moved tiles
6978 storage.redo();
6979 if(every_proc)
6980 for(auto &list : vec)
6981 for(auto &ref : list->move_refs)
6982 ref->forEach(every_proc);
6983 return true;
6984 }
6985 bool handle_tile_move(TileMoveProcess dest_process)
6986 {
6987 return _handle_tile_move(dest_process, nullopt, 0);
6988 }
6989 bool handle_tile_move(TileMoveProcess dest_process, TileMoveProcess source_process, int diff, TileMoveUndo& on_undo)
6990 {
6991 return _handle_tile_move(dest_process, source_process, diff, &on_undo);
6992 }
6993 void for_every_used_tile(std::function<void(int32_t)> proc)
6994 {
6995 reset_combo_animations();
6996 reset_combo_animations2();
6997 TileMoveProcess all_tiles {.rect = false, ._first = 0, ._last = NEWMAXTILES-1};
6998 _handle_tile_move(all_tiles, nullopt, 0, nullptr, proc, TileMoveList::Mode::CHECK_ALL);
6999 }
7000
7001 bool _handle_combo_move(ComboMoveProcess dest_process, optional<ComboMoveProcess> source_process, int diff, ComboMoveUndo* on_undo)
7002 {
7003 bool move = source_process.has_value();
7004 ComboMoveUndo local_undo;
7005 ComboMoveUndo& storage = on_undo ? *on_undo : local_undo;
7006 auto& vec = storage.vec;
7007 auto& combo_links = storage.combo_links;
7008 storage.diff = diff;
7009 storage.state = false;
7010 //Combo relative links
7011 {
7012 for(int32_t q = 0; q < MAXCOMBOS; ++q)
7013 {
7014 newcombo& cmb = combobuf[q];
7015 for(size_t idx = 0; idx < cmb.triggers.size(); ++idx)
7016 {
7017 auto& trig = cmb.triggers[idx];
7018 if(trig.trigchange)
7019 combo_links.add_to(q, q+trig.trigchange);
7020 }
7021 bool next = cmb.flag == mfSECRETSNEXT;
7022 switch(cmb.type)
7023 {
7024 case cPOUND:
7025 case cLOCKBLOCK: case cLOCKBLOCK2:
7026 case cBOSSLOCKBLOCK: case cBOSSLOCKBLOCK2:
7027 case cCHEST: case cCHEST2:
7028 case cLOCKEDCHEST: case cLOCKEDCHEST2:
7029 case cBOSSCHEST: case cBOSSCHEST2:
7030 case cSTEP: case cSTEPSAME: case cSTEPALL: case cSTEPCOPY:
7031 case cSLASHNEXT: case cSLASHNEXTITEM: case cBUSHNEXT:
7032 case cSLASHNEXTTOUCHY: case cSLASHNEXTITEMTOUCHY: case cBUSHNEXTTOUCHY:
7033 case cTALLGRASSNEXT: case cCRUMBLE:
7034 next = true;
7035 break;
7036 case cCSWITCH: case cCSWITCHBLOCK:
7037 combo_links.add_to(q, q+cmb.attributes[0]);
7038 break;
7039 case cLIGHTTARGET:
7040 if(cmb.usrflags & cflag1)
7041 combo_links.add_to(q, q-1);
7042 else next = true;
7043 break;
7044 case cSTEPSFX:
7045 if((cmb.usrflags&(cflag1|cflag3)) == cflag1)
7046 next = true;
7047 break;
7048 }
7049 if(next)
7050 combo_links.add_to(q, q+1);
7051 }
7052 }
7053
7054 //This function is expensive! Any optimizations possible should be made. -Em
7055
7056 //OPT: Check for a 0-val preemptively, to avoid processing the fmt::format strings
7057 #define ADDC(ptr, str) \
7058 if(*ptr) movelist->add_combo(ptr, ComboProtection ? str : "");
7059 #define ADDC_10k(ptr, str) \
7060 if(*ptr) movelist->add_combo_10k(ptr, ComboProtection ? str : "");
7061 //Combos
7062 {
7063 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7064 combo_links, dest_process, source_process,
7065 move
7066 ? "The combos used by the following combos will be partially cleared by the move."
7067 : "The combos used by the following combos will be partially or completely overwritten by this process."
7068 ));
7069 for(int32_t q = 0; q < MAXCOMBOS; ++q)
7070 {
7071 newcombo& cmb = combobuf[q];
7072 auto lbl = fmt::format("{}{}", q, cmb.label.empty() ? ""
7073 : fmt::format(" ({})", cmb.label));
7074 ADDC(&cmb.nextcombo, fmt::format("{} - Combo Cycle", lbl));
7075 ADDC(&cmb.liftcmb, fmt::format("{} - Lift Combo", lbl));
7076 ADDC(&cmb.liftundercmb, fmt::format("{} - Lift Undercombo", lbl));
7077 for(auto& trig : cmb.triggers)
7078 ADDC(&trig.prompt_cid, fmt::format("{} - Triggers ButtonPrompt", lbl));
7079
7080 //type-specific
7081 char const* type_name = ZI.getComboTypeName(cmb.type);
7082 switch(cmb.type)
7083 {
7084 case cLOCKEDCHEST: case cBOSSCHEST:
7085 if(cmb.usrflags & cflag13)
7086 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
7087 [[fallthrough]];
7088 case cCHEST:
7089 if(cmb.usrflags & cflag13)
7090 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7091 break;
7092 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
7093 if(cmb.usrflags & cflag13)
7094 {
7095 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7096 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
7097 }
7098 break;
7099 case cSIGNPOST:
7100 if(cmb.usrflags & cflag13)
7101 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7102 break;
7103 case cBUTTONPROMPT:
7104 if(cmb.usrflags & cflag13)
7105 ADDC_10k(&cmb.attributes[0], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7106 break;
7107 }
7108 }
7109
7110 if(!movelist->check_prot())
7111 return false;
7112 }
7113 //Door Combo Sets
7114 {
7115 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7116 combo_links, dest_process, source_process,
7117 move
7118 ? "The combos used by the following screens will be partially cleared by the move."
7119 : "The combos used by the following screens will be partially or completely overwritten by this process."
7120 ));
7121 static const char* door_names[9] = {
7122 "Wall", "Locked", "Shuttered", "Boss", "Bombed", "Open", "Unlocked", "Open Shuttered", "Open Boss"
7123 };
7124 for(int32_t i=0; i<MAXDOORCOMBOSETS; i++)
7125 {
7126 auto& dcs = DoorComboSets[i];
7127 auto& name = DoorComboSetNames[i];
7128 for(int32_t j=0; j<9; j++)
7129 {
7130 if(j<4)
7131 {
7132 ADDC(&dcs.walkthroughcombo[j], fmt::format("{} ({}): Walk-Through {}", i, name, j));
7133
7134 if(j<3)
7135 {
7136 if(j<2)
7137 {
7138 ADDC(&dcs.bombdoorcombo_u[j], fmt::format("{} ({}): Unused? bombdoorcombo_u {}", i, name, j));
7139 ADDC(&dcs.bombdoorcombo_d[j], fmt::format("{} ({}): Unused? bombdoorcombo_d {}", i, name, j));
7140 }
7141 ADDC(&dcs.bombdoorcombo_l[j], fmt::format("{} ({}): Unused? bombdoorcombo_l {}", i, name, j));
7142 ADDC(&dcs.bombdoorcombo_r[j], fmt::format("{} ({}): Unused? bombdoorcombo_r {}", i, name, j));
7143 }
7144 }
7145
7146 for(int32_t k=0; k<6; k++)
7147 {
7148 if(k<4)
7149 {
7150 ADDC(&dcs.doorcombo_u[j][k], fmt::format("{} ({}): Top, {} #{}", i, name, door_names[j], k));
7151 ADDC(&dcs.doorcombo_d[j][k], fmt::format("{} ({}): Bottom, {} #{}", i, name, door_names[j], k));
7152 }
7153
7154 ADDC(&dcs.doorcombo_l[j][k], fmt::format("{} ({}): Left, {} #{}", i, name, door_names[j], k));
7155 ADDC(&dcs.doorcombo_r[j][k], fmt::format("{} ({}): Right, {} #{}", i, name, door_names[j], k));
7156 }
7157 }
7158 }
7159
7160 if(!movelist->check_prot())
7161 return false;
7162 }
7163 //Combo Pools
7164 {
7165 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7166 combo_links, dest_process, source_process,
7167 move
7168 ? "The combos used by the following combo pools will be partially cleared by the move."
7169 : "The combos used by the following combo pools will be partially or completely overwritten by this process."
7170 ));
7171 for(auto q = 0; q < MAXCOMBOPOOLS; ++q)
7172 {
7173 combo_pool& pool = combo_pools[q];
7174 int idx = 0;
7175 for(cpool_entry& cp : pool.combos)
7176 ADDC(&cp.cid, fmt::format("{} index {}", q, idx++));
7177 }
7178
7179 if(!movelist->check_prot())
7180 return false;
7181 }
7182 //Auto Combos
7183 {
7184 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7185 combo_links, dest_process, source_process,
7186 move
7187 ? "The combos used by the following autocombos will be partially cleared by the move."
7188 : "The combos used by the following autocombos will be partially or completely overwritten by this process."
7189 ));
7190 for (auto q = 0; q < MAXAUTOCOMBOS; ++q)
7191 {
7192 combo_auto& cauto = combo_autos[q];
7193 int idx = 0;
7194 for (autocombo_entry& ac : cauto.combos)
7195 ADDC(&ac.cid, fmt::format("{} index {}", q, idx++));
7196 ADDC(&cauto.cid_erase, fmt::format("{} Erase Combo", q));
7197 ADDC(&cauto.cid_display, fmt::format("{} Display Combo", q));
7198 }
7199
7200 if(!movelist->check_prot())
7201 return false;
7202 }
7203 //Combo Aliases
7204 {
7205 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7206 combo_links, dest_process, source_process,
7207 move
7208 ? "The combos used by the following aliases will be partially cleared by the move."
7209 : "The combos used by the following aliases will be partially or completely overwritten by this process."
7210 ));
7211 for(int32_t i=0; i<MAXCOMBOALIASES; i++)
7212 {
7213 //dimensions are 1 less than you would expect -DD
7214 int32_t count=(comboa_lmasktotal(combo_aliases[i].layermask)+1)*(combo_aliases[i].width+1)*(combo_aliases[i].height+1);
7215
7216 for(int32_t j=0; j<count; j++)
7217 {
7218 ADDC(&combo_aliases[i].combos[j], fmt::format("{} index {}", i, j));
7219 }
7220 }
7221
7222 if(!movelist->check_prot())
7223 return false;
7224 }
7225 //Favorite Combos
7226 {
7227 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7228 combo_links, dest_process, source_process,
7229 move
7230 ? "The combos used by the following favorite combos will be partially cleared by the move."
7231 : "The combos used by the following favorite combos will be partially or completely overwritten by this process."
7232 ));
7233 for(int32_t i=0; i<MAXFAVORITECOMBOS; i++)
7234 {
7235 if(favorite_combo_modes[i] != dm_normal) //don't hit pools/aliases/autos, only combos!
7236 continue;
7237 ADDC(&favorite_combos[i], fmt::format("Favorite {}", i));
7238 }
7239
7240 if(!movelist->check_prot())
7241 return false;
7242 }
7243 //Bottle Shops
7244 {
7245 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7246 combo_links, dest_process, source_process,
7247 move
7248 ? "The combos used by the following bottle shops will be partially cleared by the move."
7249 : "The combos used by the following bottle shops will be partially or completely overwritten by this process."
7250 ));
7251 for(auto q = 0; q < 256; ++q)
7252 for(auto p = 0; p < 3; ++p)
7253 ADDC(&QMisc.bottle_shop_types[q].comb[p], fmt::format("{} slot {}", q, p));
7254
7255 if(!movelist->check_prot())
7256 return false;
7257 }
7258 //Screens //EXPENSIVE! DO THIS LAST!
7259 {
7260 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7261 combo_links, dest_process, source_process,
7262 move
7263 ? "The combos used by the following screens will be partially cleared by the move."
7264 : "The combos used by the following screens will be partially or completely overwritten by this process."
7265 ));
7266
7267 for(int32_t i=0; i<map_count && i<MAXMAPS; i++)
7268 {
7269 for(int32_t j=0; j<MAPSCRS; j++)
7270 {
7271 mapscr& scr = TheMaps[i*MAPSCRS+j];
7272
7273 if(!(scr.valid&mVALID))
7274 continue;
7275
7276 ADDC(&scr.undercombo, fmt::format("{}x{:02X} - UnderCombo", i, j));
7277
7278 // Specifying the exact position is too expensive - too much string creation.
7279 std::string data_str = ComboProtection ? fmt::format("{}x{:02X} - Combo", i, j) : "";
7280 for(int32_t k=0; k<176; k++)
7281 ADDC(&scr.data[k], data_str);
7282
7283 for(int32_t k=0; k<128; k++)
7284 ADDC(&scr.secretcombo[k], fmt::format("{}x{:02X} - SecretCombo {}", i, j, k));
7285
7286 word maxffc = scr.numFFC();
7287 for(word k=0; k<maxffc; k++)
7288 {
7289 ffcdata& ffc = scr.ffcs[k];
7290 ADDC(&ffc.data, fmt::format("{}x{:02X} - FFC {}", i, j, k+1));
7291 }
7292 }
7293 }
7294
7295 if(!movelist->check_prot())
7296 return false;
7297 }
7298 if(source_process) //Apply the 'diff' value to all moved combos
7299 storage.redo();
7300 return true;
7301 }
7302
7303 bool handle_combo_move(ComboMoveProcess dest_process)
7304 {
7305 return _handle_combo_move(dest_process, nullopt, 0, nullptr);
7306 }
7307 bool handle_combo_move(ComboMoveProcess dest_process, ComboMoveProcess source_process, int diff, ComboMoveUndo& on_undo)
7308 {
7309 return _handle_combo_move(dest_process, source_process, diff, &on_undo);
7310 }
7311 void register_used_tiles()
7312 {
7313 memset(used_tile_table, 0, sizeof(used_tile_table));
7314 for_every_used_tile([&](int tile)
7315 {
7316 used_tile_table[tile] = true;
7317 });
7318 }
7319
7320 bool overlay_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move, int32_t cs, bool backwards)
7321 {
7322 bool ctrl=(CHECK_CTRL_CMD);
7323 bool copied=false;
7324 copied=overlay_tiles_united(tile,tile2,copy,copycnt,rect_sel,move,cs,backwards);
7325
7326 if(copied)
7327 {
7328 saved=false;
7329 }
7330
7331 return copied;
7332 }
7333
7334 bool overlay_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move, int32_t cs, bool backwards)
7335 {
7336 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7337 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7338
7339 // if tile>tile2 then swap them
7340 if(tile>tile2)
7341 {
7342 zc_swap(tile, tile2);
7343 }
7344
7345 // alt=copy from right
7346 // shift=copy from bottom
7347
7348 int32_t copies=copycnt;
7349 int32_t dest_first=tile;
7350 int32_t dest_last=tile2;
7351 int32_t src_first=copy;
7352 int32_t src_last=copy+copies-1;
7353
7354 int32_t dest_top=0;
7355 int32_t dest_bottom=0;
7356 int32_t src_top=0;
7357 int32_t src_bottom=0;
7358 int32_t src_left=0, src_right=0;
7359 int32_t src_width=0, src_height=0;
7360 int32_t dest_left=0, dest_right=0;
7361 int32_t dest_width=0, dest_height=0;
7362 int32_t rows=0, cols=0;
7363
7364 if(rect)
7365 {
7366 dest_top=TILEROW(dest_first);
7367 dest_bottom=TILEROW(dest_last);
7368 src_top=TILEROW(src_first);
7369 src_bottom=TILEROW(src_last);
7370
7371 src_left= zc_min(TILECOL(src_first),TILECOL(src_last));
7372 src_right=zc_max(TILECOL(src_first),TILECOL(src_last));
7373 src_first=(src_top * TILES_PER_ROW)+src_left;
7374 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7375
7376 dest_left= zc_min(TILECOL(dest_first),TILECOL(dest_last));
7377 dest_right=zc_max(TILECOL(dest_first),TILECOL(dest_last));
7378 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7379 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7380
7381 //if no dest range set, then set one
7382 if((dest_first==dest_last)&&(src_first!=src_last))
7383 {
7384 if(alt)
7385 {
7386 dest_left=dest_right-(src_right-src_left);
7387 }
7388 else
7389 {
7390 dest_right=dest_left+(src_right-src_left);
7391 }
7392
7393 if(shift)
7394 {
7395 dest_top=dest_bottom-(src_bottom-src_top);
7396 }
7397 else
7398 {
7399 dest_bottom=dest_top+(src_bottom-src_top);
7400 }
7401
7402 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7403 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7404 }
7405 else
7406 {
7407 if(dest_right-dest_left<src_right-src_left) //destination is shorter than source
7408 {
7409 if(alt) //copy from right tile instead of left
7410 {
7411 src_left=src_right-(dest_right-dest_left);
7412 }
7413 else //copy from left tile
7414 {
7415 src_right=src_left+(dest_right-dest_left);
7416 }
7417 }
7418 else if(dest_right-dest_left>src_right-src_left) //destination is longer than source
7419 {
7420 if(alt) //copy from right tile instead of left
7421 {
7422 dest_left=dest_right-(src_right-src_left);
7423 }
7424 else //copy from left tile
7425 {
7426 dest_right=dest_left+(src_right-src_left);
7427 }
7428 }
7429
7430 if(dest_bottom-dest_top<src_bottom-src_top) //destination is shorter than source
7431 {
7432 if(shift) //copy from bottom tile instead of top
7433 {
7434 src_top=src_bottom-(dest_bottom-dest_top);
7435 }
7436 else //copy from top tile
7437 {
7438 src_bottom=src_top+(dest_bottom-dest_top);
7439 }
7440 }
7441 else if(dest_bottom-dest_top>src_bottom-src_top) //destination is longer than source
7442 {
7443 if(shift) //copy from bottom tile instead of top
7444 {
7445 dest_top=dest_bottom-(src_bottom-src_top);
7446 }
7447 else //copy from top tile
7448 {
7449 dest_bottom=dest_top+(src_bottom-src_top);
7450 }
7451 }
7452
7453 src_first=(src_top * TILES_PER_ROW)+src_left;
7454 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7455 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7456 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7457 }
7458
7459 cols=src_right-src_left+1;
7460 rows=src_bottom-src_top+1;
7461
7462 dest_width=dest_right-dest_left+1;
7463 dest_height=dest_bottom-dest_top+1;
7464 src_width=src_right-src_left+1;
7465 src_height=src_bottom-src_top+1;
7466
7467 }
7468 else //!rect
7469 {
7470 //if no dest range set, then set one
7471 if((dest_first==dest_last)&&(src_first!=src_last))
7472 {
7473 if(alt)
7474 {
7475 dest_first=dest_last-(src_last-src_first);
7476 }
7477 else
7478 {
7479 dest_last=dest_first+(src_last-src_first);
7480 }
7481 }
7482 else
7483 {
7484 if(dest_last-dest_first<src_last-src_first) //destination is shorter than source
7485 {
7486 if(alt) //copy from last tile instead of first
7487 {
7488 src_first=src_last-(dest_last-dest_first);
7489 }
7490 else //copy from first tile
7491 {
7492 src_last=src_first+(dest_last-dest_first);
7493 }
7494 }
7495 else if(dest_last-dest_first>src_last-src_first) //destination is longer than source
7496 {
7497 if(alt) //copy from last tile instead of first
7498 {
7499 dest_first=dest_last-(src_last-src_first);
7500 }
7501 else //copy from first tile
7502 {
7503 dest_last=dest_first+(src_last-src_first);
7504 }
7505 }
7506 }
7507
7508 copies=dest_last-dest_first+1;
7509 }
7510
7511
7512
7513 char buf2[80], buf3[80], buf4[80];
7514 sprintf(buf2, " ");
7515 sprintf(buf3, " ");
7516 sprintf(buf4, " ");
7517
7518 // warn if range extends beyond last tile
7519 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7520
7521 if(dest_last>=NEWMAXTILES)
7522 {
7523 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7524 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7525 return false;
7526 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7527 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7528 // {
7529 // return false;
7530 // }
7531 }
7532
7533
7534 TileMoveUndo on_undo;
7535 // Overwrite warnings
7536 TileMoveProcess dest{rect, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last};
7537 if(move)
7538 {
7539 TileMoveProcess src{rect, src_left, src_top, src_width, src_height, src_first, src_last};
7540 if(!handle_tile_move(dest, src, dest_first-src_first, on_undo))
7541 return false;
7542 }
7543 else
7544 {
7545 if(!handle_tile_move(dest))
7546 return false;
7547 }
7548 // copy tiles and delete if needed (move)
7549
7550 {
7551 go_tiles();
7552
7553 int32_t diff=dest_first-src_first;
7554
7555 if(rect)
7556 {
7557 for(int32_t r=0; r<rows; ++r)
7558 {
7559 for(int32_t c=0; c<cols; ++c)
7560 {
7561 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
7562 int32_t st=(src_first+((r*TILES_PER_ROW)+c));
7563
7564 if(dt>=NEWMAXTILES)
7565 continue;
7566
7567 overlay_tile(newtilebuf,dt,st,cs,backwards);
7568
7569 }
7570 }
7571 }
7572 else
7573 {
7574 for(int32_t c=0; c<copies; ++c)
7575 {
7576 int32_t dt=(dest_first+c);
7577 int32_t st=(src_first+c);
7578
7579 if(dt>=NEWMAXTILES)
7580 continue;
7581
7582 overlay_tile(newtilebuf,dt,st,cs,backwards);
7583
7584 if(move)
7585 {
7586 if(st<dest_first||st>(dest_first+c-1))
7587 reset_tile(newtilebuf, st, tf4Bit);
7588 }
7589 }
7590 }
7591 }
7592
7593 //now that tiles have moved, fix these buffers -DD
7594 register_blank_tiles();
7595 register_used_tiles();
7596
7597 if(move)
7598 last_tile_move_list = std::move(on_undo);
7599 return true;
7600 }
7601 //
7602 bool do_movetile_united(tile_move_data const& tmd)
7603 {
7604 char buf2[80], buf3[80], buf4[80];
7605 sprintf(buf2, " ");
7606 sprintf(buf3, " ");
7607 sprintf(buf4, " ");
7608
7609 // warn if range extends beyond last tile
7610 sprintf(buf4, "Some tiles will not be %s", tmd.move?"moved.":"copied.");
7611
7612 if(tmd.dest_last>=NEWMAXTILES)
7613 {
7614 sprintf(buf4, "%s operation cancelled.", tmd.move?"Move":"Copy");
7615 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7616 return false;
7617 }
7618
7619 TileMoveUndo on_undo;
7620 // Overwrite warnings
7621 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7622 if(tmd.move)
7623 {
7624 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7625 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7626 return false;
7627 }
7628 else
7629 {
7630 if(!handle_tile_move(dest))
7631 return false;
7632 }
7633
7634 // copy tiles and delete if needed (tmd.move)
7635 {
7636 go_tiles();
7637
7638 if(tmd.rect)
7639 {
7640 for(int32_t r=0; r<tmd.rows; ++r)
7641 {
7642 for(int32_t c=0; c<tmd.cols; ++c)
7643 {
7644 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7645 int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7646
7647 if(dt>=NEWMAXTILES)
7648 continue;
7649
7650 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7651
7652 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7653 {
7654 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7655 }
7656
7657 if(tmd.move)
7658 {
7659 if((st<tmd.dest_first||st>tmd.dest_first+((tmd.rows-1)*TILES_PER_ROW)+(tmd.cols-1)))
7660 reset_tile(newtilebuf, st, tf4Bit);
7661 else
7662 {
7663 int32_t destLeft=tmd.dest_first%TILES_PER_ROW;
7664 int32_t destRight=(tmd.dest_first+tmd.cols-1)%TILES_PER_ROW;
7665 if(destLeft<=destRight)
7666 {
7667 if(st%TILES_PER_ROW<destLeft || st%TILES_PER_ROW>destRight)
7668 reset_tile(newtilebuf, st, tf4Bit);
7669 }
7670 else // Wrapped around
7671 {
7672 if(st%TILES_PER_ROW<destLeft && st%TILES_PER_ROW>destRight)
7673 reset_tile(newtilebuf, st, tf4Bit);
7674 }
7675 }
7676 }
7677 }
7678 }
7679 }
7680 else
7681 {
7682 for(int32_t c=0; c<tmd.copies; ++c)
7683 {
7684 int32_t dt=(tmd.dest_first+c);
7685 int32_t st=(tmd.src_first+c);
7686
7687 if(dt>=NEWMAXTILES)
7688 continue;
7689
7690 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7691
7692 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7693 {
7694 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7695 }
7696
7697 if(tmd.move)
7698 {
7699 if(st<tmd.dest_first||st>(tmd.dest_first+c-1))
7700 reset_tile(newtilebuf, st, tf4Bit);
7701 }
7702 }
7703 }
7704 }
7705
7706 //now that tiles have moved, fix these buffers -DD
7707 register_blank_tiles();
7708 register_used_tiles();
7709
7710 if(tmd.move)
7711 last_tile_move_list = std::move(on_undo);
7712 return true;
7713 }
7714
7715 bool copy_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7716 {
7717 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7718 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7719
7720 // if tile>tile2 then swap them
7721 if(tile>tile2)
7722 {
7723 zc_swap(tile, tile2);
7724 }
7725
7726 // alt=copy from right
7727 // shift=copy from bottom
7728 tile_move_data tmd;
7729
7730 tmd.copies=copycnt;
7731 tmd.dest_first=tile;
7732 tmd.dest_last=tile2;
7733 tmd.src_first=copy;
7734 tmd.src_last=copy+tmd.copies-1;
7735 tmd.rect = rect;
7736 tmd.move = move;
7737
7738 if(rect)
7739 {
7740 tmd.dest_top=TILEROW(tmd.dest_first);
7741 tmd.dest_bottom=TILEROW(tmd.dest_last);
7742 tmd.src_top=TILEROW(tmd.src_first);
7743 tmd.src_bottom=TILEROW(tmd.src_last);
7744
7745 tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7746 tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7747 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7748 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7749
7750 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7751 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7752 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7753 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7754
7755 //if no dest range set, then set one
7756 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7757 {
7758 if(alt)
7759 {
7760 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7761 }
7762 else
7763 {
7764 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7765 }
7766
7767 if(shift)
7768 {
7769 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7770 }
7771 else
7772 {
7773 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7774 }
7775
7776 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7777 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7778 }
7779 else
7780 {
7781 if(tmd.dest_right-tmd.dest_left<tmd.src_right-tmd.src_left) //destination is shorter than source
7782 {
7783 if(alt) //copy from right tile instead of left
7784 {
7785 tmd.src_left=tmd.src_right-(tmd.dest_right-tmd.dest_left);
7786 }
7787 else //copy from left tile
7788 {
7789 tmd.src_right=tmd.src_left+(tmd.dest_right-tmd.dest_left);
7790 }
7791 }
7792 else if(tmd.dest_right-tmd.dest_left>tmd.src_right-tmd.src_left) //destination is longer than source
7793 {
7794 if(alt) //copy from right tile instead of left
7795 {
7796 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7797 }
7798 else //copy from left tile
7799 {
7800 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7801 }
7802 }
7803
7804 if(tmd.dest_bottom-tmd.dest_top<tmd.src_bottom-tmd.src_top) //destination is shorter than source
7805 {
7806 if(shift) //copy from bottom tile instead of top
7807 {
7808 tmd.src_top=tmd.src_bottom-(tmd.dest_bottom-tmd.dest_top);
7809 }
7810 else //copy from top tile
7811 {
7812 tmd.src_bottom=tmd.src_top+(tmd.dest_bottom-tmd.dest_top);
7813 }
7814 }
7815 else if(tmd.dest_bottom-tmd.dest_top>tmd.src_bottom-tmd.src_top) //destination is longer than source
7816 {
7817 if(shift) //copy from bottom tile instead of top
7818 {
7819 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7820 }
7821 else //copy from top tile
7822 {
7823 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7824 }
7825 }
7826
7827 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7828 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7829 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7830 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7831 }
7832
7833 tmd.cols=tmd.src_right-tmd.src_left+1;
7834 tmd.rows=tmd.src_bottom-tmd.src_top+1;
7835
7836 tmd.dest_width=tmd.dest_right-tmd.dest_left+1;
7837 tmd.dest_height=tmd.dest_bottom-tmd.dest_top+1;
7838 tmd.src_width=tmd.src_right-tmd.src_left+1;
7839 tmd.src_height=tmd.src_bottom-tmd.src_top+1;
7840
7841 }
7842 else //!rect
7843 {
7844 //if no dest range set, then set one
7845 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7846 {
7847 if(alt)
7848 {
7849 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7850 }
7851 else
7852 {
7853 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7854 }
7855 }
7856 else
7857 {
7858 if(tmd.dest_last-tmd.dest_first<tmd.src_last-tmd.src_first) //destination is shorter than source
7859 {
7860 if(alt) //copy from last tile instead of first
7861 {
7862 tmd.src_first=tmd.src_last-(tmd.dest_last-tmd.dest_first);
7863 }
7864 else //copy from first tile
7865 {
7866 tmd.src_last=tmd.src_first+(tmd.dest_last-tmd.dest_first);
7867 }
7868 }
7869 else if(tmd.dest_last-tmd.dest_first>tmd.src_last-tmd.src_first) //destination is longer than source
7870 {
7871 if(alt) //copy from last tile instead of first
7872 {
7873 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7874 }
7875 else //copy from first tile
7876 {
7877 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7878 }
7879 }
7880 }
7881
7882 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7883 }
7884
7885 return do_movetile_united(tmd);
7886 }
7887
7888 //
7889
7890 bool copy_tiles_united_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7891 {
7892 assert(!move); //not implemented
7893
7894 // if tile>tile2 then swap them
7895 if(tile>tile2)
7896 {
7897 zc_swap(tile, tile2);
7898 }
7899
7900 tile_move_data tmd;
7901 tmd.copies=copycnt;
7902 tmd.dest_first=tile;
7903 tmd.dest_last=tile2;
7904 tmd.src_first=copy;
7905 tmd.src_last=copy+tmd.copies-1;
7906
7907
7908
7909 if(rect)
7910 {
7911 tmd.dest_top=TILEROW(tmd.dest_first);
7912 tmd.dest_bottom=TILEROW(tmd.dest_last);
7913 //tmd.src_top=TILEROW(tmd.src_first);
7914 //tmd.src_bottom=TILEROW(tmd.src_last);
7915
7916 //tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7917 //tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7918 //tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7919 //tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7920
7921 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7922 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7923 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7924 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7925
7926
7927
7928
7929 tmd.dest_width=tmd.dest_right-tmd.dest_left;
7930 tmd.dest_height=tmd.dest_bottom-tmd.dest_top;
7931
7932 tmd.cols=tmd.dest_width+1;
7933 tmd.rows=tmd.dest_height+1;
7934
7935 al_trace("tmd.rows: %d\n", tmd.rows);
7936 al_trace("tmd.cols: %d\n", tmd.cols);
7937
7938
7939 }
7940 else //!rect
7941 {
7942 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7943 }
7944
7945
7946
7947 char buf2[80], buf3[80], buf4[80];
7948 sprintf(buf2, " ");
7949 sprintf(buf3, " ");
7950 sprintf(buf4, " ");
7951
7952 // warn if range extends beyond last tile
7953 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7954
7955 if(tmd.dest_last>=NEWMAXTILES)
7956 {
7957 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7958 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7959 return false;
7960 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7961 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7962 // {
7963 // return false;
7964 // }
7965 }
7966
7967 TileMoveUndo on_undo;
7968 // Overwrite warnings
7969 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7970 if(tmd.move)
7971 {
7972 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7973 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7974 return false;
7975 }
7976 else
7977 {
7978 if(!handle_tile_move(dest))
7979 return false;
7980 }
7981
7982 // copy tiles and delete if needed (move)
7983
7984 {
7985 go_tiles();
7986
7987 int32_t diff=tmd.dest_first-tmd.src_first;
7988
7989 if(rect)
7990 {
7991 al_trace("floodfill, rect\n");
7992 al_trace("tmd.rows: %d\n", tmd.rows);
7993 al_trace("tmd.cols: %d\n", tmd.cols);
7994 for(int32_t r=0; r<tmd.rows; ++r)
7995 {
7996 for(int32_t c=0; c<tmd.cols; ++c)
7997 {
7998 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7999 //int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
8000
8001 if(dt>=NEWMAXTILES)
8002 continue;
8003
8004 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
8005
8006 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
8007 {
8008 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
8009 }
8010 }
8011 }
8012 }
8013 else
8014 {
8015 for(int32_t c=0; c<tmd.copies; ++c)
8016 {
8017 int32_t dt=(tmd.dest_first+c);
8018 int32_t st=(tmd.src_first+c);
8019
8020 if(dt>=NEWMAXTILES)
8021 continue;
8022
8023 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
8024
8025 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
8026 {
8027 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
8028 }
8029
8030 }
8031 }
8032 }
8033
8034 //now that tiles have moved, fix these buffers -DD
8035 register_blank_tiles();
8036 register_used_tiles();
8037
8038 if(tmd.move)
8039 last_tile_move_list = std::move(on_undo);
8040 return true;
8041 }
8042 //
8043
8044 bool copy_tiles_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
8045 {
8046 al_trace("Floodfill Psste\n");
8047 bool ctrl=(CHECK_CTRL_CMD);
8048 bool copied=false;
8049 copied=copy_tiles_united_floodfill(tile,tile2,copy,copycnt,rect_sel,move);
8050
8051 if(copied)
8052 {
8053 if(!ctrl)
8054 {
8055 copy=-1;
8056 tile2=tile;
8057 }
8058
8059 saved=false;
8060 }
8061
8062 return copied;
8063 }
8064
8065 bool copy_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
8066 {
8067 bool ctrl=(CHECK_CTRL_CMD);
8068 bool copied=false;
8069 copied=copy_tiles_united(tile,tile2,copy,copycnt,rect_sel,move);
8070
8071 if(copied)
8072 {
8073 if(!ctrl)
8074 {
8075 copy=-1;
8076 tile2=tile;
8077 }
8078
8079 saved=false;
8080 }
8081
8082 return copied;
8083 }
8084
8085 bool scale_or_rotate_tiles(int32_t &tile, int32_t &tile2, int32_t &cs, bool rotate)
8086 {
8087 // if tile>tile2 then swap them
8088 if(tile>tile2)
8089 {
8090 zc_swap(tile, tile2);
8091 }
8092 int32_t src_top = TILEROW(tile);
8093 int32_t src_bottom = TILEROW(tile2);
8094 int32_t src_left = zc_min(TILECOL(tile),TILECOL(tile2));
8095 int32_t src_right = zc_max(TILECOL(tile),TILECOL(tile2));
8096 int32_t src_first = (src_top * TILES_PER_ROW)+src_left;
8097 int32_t src_last = (src_bottom*TILES_PER_ROW)+src_right;
8098
8099 int32_t src_width = src_right-src_left+1,
8100 src_height = src_bottom-src_top+1;
8101 int32_t dest_width = src_width, dest_height = src_height;
8102 zfix dest_rot = 0_zf;
8103 if(rotate)
8104 RotateTileDialog(&dest_width, &dest_height, &dest_rot).show();
8105 else
8106 ScaleTileDialog(&dest_width, &dest_height).show();
8107 if (rotate)
8108 {
8109 if (dest_rot == 0) return false;
8110 }
8111 else
8112 {
8113 if (dest_width == src_width && dest_height == src_height) return false; //no scaling
8114 }
8115 dest_width = vbound(dest_width, 1, 20);
8116 dest_height = vbound(dest_height, 1, 20);
8117
8118 int32_t dest_top = src_top;
8119 int32_t dest_bottom = src_top+dest_height-1;
8120 int32_t dest_left = src_left;
8121 int32_t dest_right = src_left+dest_width-1;
8122 int32_t dest_first = src_first;
8123 int32_t dest_last = (dest_bottom*TILES_PER_ROW)+dest_right;
8124
8125
8126 if(dest_last>=NEWMAXTILES)
8127 {
8128 InfoDialog("Destination Error", "The destination extends beyond the last available tile row. Scale operation cancelled.").show();
8129 return false;
8130 }
8131
8132 // Overwrite warnings
8133 if(!handle_tile_move({true, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last}))
8134 return false;
8135
8136 //Do the rotate
8137 {
8138 go_tiles();
8139
8140 int32_t diff=dest_first-src_first;
8141 BITMAP *srcbmp = create_bitmap_ex(8,src_width*16,src_height*16),
8142 *destbmp = create_bitmap_ex(8,dest_width*16,dest_height*16);
8143 clear_bitmap(srcbmp); clear_bitmap(destbmp);
8144 overtileblock16(srcbmp, src_first, 0, 0, src_width, src_height, cs, 0);
8145 bool is8bit = newtilebuf[src_first].format == tf8Bit;
8146 if (rotate)
8147 {
8148 rotate_sprite(destbmp, srcbmp, 0, 0, ftofix(dest_rot * 0.7111111111111));
8149 }
8150 else
8151 {
8152 stretch_blit(srcbmp, destbmp, 0, 0, srcbmp->w, srcbmp->h,
8153 0, 0, destbmp->w, destbmp->h);
8154 }
8155 int32_t mhei = zc_max(src_height,dest_height),
8156 mwid = zc_max(src_width, dest_width);
8157 for(int32_t r=0; r<mhei; ++r)
8158 {
8159 for(int32_t c=0; c<mwid; ++c)
8160 {
8161 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
8162
8163 if(dt>=NEWMAXTILES)
8164 continue;
8165 if(r < dest_height && c < dest_width)
8166 {
8167 write_tile(newtilebuf, destbmp, dt, c*16, r*16, is8bit, false);
8168 }
8169 else reset_tile(newtilebuf, dt, tf4Bit);
8170 }
8171 }
8172 }
8173
8174 register_blank_tiles();
8175 register_used_tiles();
8176 return true;
8177 }
8178
8179 void copy_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool masscopy)
8180 {
8181 //these 2 shouldn't be needed, but just to be safe...
8182 reset_combo_animations();
8183 reset_combo_animations2();
8184
8185 if(tile2<tile)
8186 {
8187 zc_swap(tile,tile2);
8188 }
8189
8190 auto first = tile;
8191 auto last = masscopy ? tile2 : first + copycnt-1;
8192 if(!handle_combo_move({first,last}))
8193 return;
8194
8195 if(!masscopy)
8196 {
8197 if(tile==copy)
8198 {
8199 copy=-1;
8200 tile2=tile;
8201 return;
8202 }
8203
8204 // go_combos(); // commented because caller does it for us
8205 //if copying to an earlier combo, copy from left to right
8206 //otherwise, copy from right to left
8207 for(int32_t t=(tile<copy)?0:(copycnt-1); (tile<copy)?(t<copycnt):(t>=0); (tile<copy)?(t++):(t--))
8208 {
8209 if(tile+t < MAXCOMBOS)
8210 {
8211 combobuf[tile+t]=combobuf[copy+t];
8212 }
8213 }
8214
8215 copy=-1;
8216 tile2=tile;
8217 saved=false;
8218 }
8219 else
8220 {
8221 // go_combos();
8222 int32_t src=copy, dest=tile;
8223
8224 do
8225 {
8226 combobuf[dest]=combobuf[src];
8227 ++src;
8228 ++dest;
8229
8230 if((src-copy)==copycnt) src=copy;
8231 }
8232 while(dest<=tile2);
8233
8234 copy=-1;
8235 tile2=tile;
8236 saved=false;
8237 }
8238
8239 setup_combo_animations();
8240 setup_combo_animations2();
8241 }
8242
8243 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing)
8244 {
8245 reset_combo_animations();
8246 reset_combo_animations2();
8247 go_combos();
8248
8249 auto diff = cmd.tile - cmd.copy1;
8250 if(is_undoing)
8251 on_undo.undo();
8252 else if(!handle_combo_move({cmd.tile,cmd.tile+cmd.copycnt-1},{cmd.copy1,cmd.copy1+cmd.copycnt-1}, diff, on_undo))
8253 return false;
8254
8255 for(int32_t t=(cmd.tile<cmd.copy1)?0:(cmd.copycnt-1); (cmd.tile<cmd.copy1)?(t<cmd.copycnt):(t>=0); (cmd.tile<cmd.copy1)?(t++):(t--))
8256 {
8257 if(cmd.tile+t < MAXCOMBOS)
8258 {
8259 combobuf[cmd.tile+t]=combobuf[cmd.copy1+t];
8260 clear_combo(cmd.copy1+t);
8261 }
8262 }
8263
8264 setup_combo_animations();
8265 setup_combo_animations2();
8266 saved=false;
8267 return true;
8268 }
8269
8270 void move_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt)
8271 {
8272 if(tile2<tile)
8273 {
8274 zc_swap(tile,tile2);
8275 }
8276
8277 if(tile==copy)
8278 {
8279 copy=-1;
8280 tile2=tile;
8281 return;
8282 }
8283
8284 combo_move_data cmd;
8285 cmd.tile = tile;
8286 cmd.tile2 = tile2;
8287 cmd.copy1 = copy;
8288 cmd.copycnt = copycnt;
8289
8290 ComboMoveUndo on_undo;
8291 if(!do_movecombo(cmd, on_undo))
8292 return;
8293 last_combo_move_list = std::move(on_undo);
8294 copy=-1;
8295 tile2=tile;
8296 }
8297
8298 void do_delete_tiles(int32_t firsttile, int32_t lasttile, bool rect_sel)
8299 {
8300 if(firsttile > lasttile)
8301 zc_swap(firsttile,lasttile);
8302 int32_t coldiff = 0;
8303 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8304 {
8305 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8306 firsttile-=coldiff;
8307 lasttile+=coldiff;
8308 }
8309 for(int32_t t=firsttile; t<=lasttile; ++t)
8310 if(!rect_sel ||
8311 ((TILECOL(t)>=TILECOL(firsttile)) &&
8312 (TILECOL(t)<=TILECOL(lasttile))))
8313 reset_tile(newtilebuf, t, tf4Bit);
8314 saved=false;
8315 register_blank_tiles();
8316 }
8317
8318 void delete_tiles(int32_t &tile,int32_t &tile2,bool rect_sel)
8319 {
8320 char buf[40];
8321
8322 if(tile==tile2)
8323 {
8324 sprintf(buf,"Delete tile %d?",tile);
8325 }
8326 else
8327 {
8328 sprintf(buf,"Delete tiles %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
8329 }
8330
8331 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8332 {
8333 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8334
8335 go_tiles();
8336
8337 //if copying to an earlier tile, copy from left to right
8338 //otherwise, copy from right to left
8339 do_delete_tiles(firsttile, lasttile, rect_sel);
8340
8341 tile=tile2=zc_min(tile,tile2);
8342 saved=false;
8343 register_blank_tiles();
8344 }
8345 }
8346
8347 void overlay_tile2(int32_t dest,int32_t src,int32_t cs,bool backwards)
8348 {
8349 byte buf[256];
8350 go_tiles();
8351
8352 unpack_tile(newtilebuf, dest, 0, false);
8353
8354 for(int32_t i=0; i<256; i++)
8355 buf[i] = unpackbuf[i];
8356
8357 unpack_tile(newtilebuf, src, 0, false);
8358
8359 if(newtilebuf[src].format>tf4Bit)
8360 {
8361 cs=0;
8362 }
8363
8364 cs &= 15;
8365 cs <<= CSET_SHFT;
8366
8367 for(int32_t i=0; i<256; i++)
8368 {
8369 if(backwards)
8370 {
8371 if(!buf[i])
8372 {
8373 buf[i] = unpackbuf[i]+cs;
8374 }
8375 }
8376 else
8377 {
8378 if(unpackbuf[i])
8379 {
8380 buf[i] = unpackbuf[i]+cs;
8381 }
8382 }
8383 }
8384
8385 pack_tile(newtilebuf, buf,dest);
8386 saved=false;
8387 }
8388
8389 void mass_overlay_tile(int32_t dest1, int32_t dest2, int32_t src, int32_t cs, bool backwards, bool rect_sel)
8390 {
8391 //byte buf[256];
8392 go_tiles();
8393
8394 if(!rect_sel)
8395 {
8396 for(int32_t d=dest1; d <= dest2; ++d)
8397 {
8398 /*unpack_tile(newtilebuf, d, 0, false);
8399
8400 for(int32_t i=0; i<256; i++)
8401 {
8402 if(!backwards)
8403 {
8404 if(!buf[i])
8405 {
8406 buf[i] = unpackbuf[i] + cs;
8407 }
8408 }
8409 else
8410 {
8411 if(unpackbuf[i])
8412 {
8413 buf[i] = unpackbuf[i] + cs;
8414 }
8415 }
8416 }
8417
8418 pack_tile(newtilebuf, buf,d);
8419 */
8420
8421 overlay_tile(newtilebuf,d,src,cs,backwards);
8422
8423 if(!blank_tile_table[src])
8424 {
8425 blank_tile_table[d]=false;
8426 }
8427 }
8428 }
8429 else
8430 {
8431 int32_t rmin=zc_min(TILEROW(dest1),TILEROW(dest2));
8432 int32_t rmax=zc_max(TILEROW(dest1),TILEROW(dest2));
8433 int32_t cmin=zc_min(TILECOL(dest1),TILECOL(dest2));
8434 int32_t cmax=zc_max(TILECOL(dest1),TILECOL(dest2));
8435 int32_t d=0;
8436
8437 for(int32_t j=cmin; j<=cmax; ++j)
8438 {
8439 for(int32_t k=rmin; k<=rmax; ++k)
8440 {
8441 d=j+TILES_PER_ROW*k;
8442 /*unpack_tile(newtilebuf, d, 0, false);
8443
8444 for(int32_t i=0; i<256; i++)
8445 {
8446 if(!backwards)
8447 {
8448 if(!buf[i])
8449 {
8450 buf[i] = unpackbuf[i] + cs;
8451 }
8452 }
8453 else
8454 {
8455 if(unpackbuf[i])
8456 {
8457 buf[i] = unpackbuf[i] + cs;
8458 }
8459 }
8460 }
8461
8462 pack_tile(newtilebuf, buf,d);
8463 */
8464
8465 overlay_tile(newtilebuf,d,src,cs,backwards);
8466
8467 if(!blank_tile_table[src])
8468 {
8469 blank_tile_table[d]=false;
8470 }
8471 }
8472 }
8473 }
8474
8475 return;
8476 }
8477
8478 void sel_tile(int32_t &tile, int32_t &tile2, int32_t &first, int32_t type, int32_t s)
8479 {
8480 tile+=s;
8481 bound(tile,0,NEWMAXTILES-1);
8482
8483 if(type!=0 || !(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
8484 tile2 = tile;
8485
8486 first = tile - (tile%TILES_PER_PAGE);
8487 }
8488
8489 void convert_tile(int32_t t, int32_t bp2, int32_t cs, bool shift, bool alt)
8490 {
8491 int32_t cst;
8492
8493 switch(bp2)
8494 {
8495 case tf4Bit:
8496 switch(newtilebuf[t].format)
8497 {
8498 case tf4Bit:
8499 //already in the right format
8500 break;
8501
8502 case tf8Bit:
8503 unpack_tile(newtilebuf, t, 0, true);
8504
8505 if(alt) //reduce
8506 {
8507 for(int32_t i=0; i<256; i++)
8508 {
8509 if(!shift||unpackbuf[i]!=0)
8510 {
8511 unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
8512 }
8513 }
8514 }
8515 else //truncate
8516 {
8517 for(int32_t i=0; i<256; i++)
8518 {
8519 unpackbuf[i]&=15;
8520 }
8521 }
8522
8523 reset_tile(newtilebuf, t, tf4Bit);
8524 pack_tile(newtilebuf, unpackbuf, t);
8525 break;
8526 }
8527
8528 break;
8529
8530 case tf8Bit:
8531 switch(newtilebuf[t].format)
8532 {
8533 case tf4Bit:
8534 unpack_tile(newtilebuf, t, 0, true);
8535 cst = cs&15;
8536 cst <<= CSET_SHFT;
8537
8538 for(int32_t i=0; i<256; i++)
8539 {
8540 if(!shift||unpackbuf[i]!=0)
8541 {
8542 unpackbuf[i]+=cst;
8543 }
8544 }
8545
8546 reset_tile(newtilebuf, t, tf8Bit);
8547 pack_tile(newtilebuf, unpackbuf, t);
8548 break;
8549
8550 case tf8Bit:
8551 //already in the right format
8552 break;
8553 }
8554
8555 break;
8556 }
8557 }
8558
8559 static DIALOG create_relational_tiles_dlg[] =
8560 {
8561 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
8562 12 { jwin_win_proc, 0, 0, 160, 92, vc(0), vc(11), 0, D_EXIT, 0, 0, (void *) "Tile Setup", NULL, NULL },
8563 12 { jwin_rtext_proc, 74, 28, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Frames:", NULL, NULL },
8564 12 { jwin_edit_proc, 78, 24, 48, 16, 0, 0, 0, 0, 6, 0, NULL, NULL, NULL },
8565 12 { jwin_radio_proc, 8, 44, 64, 9, vc(14), vc(1), 0, D_SELECTED, 0, 0, (void *) "Relational", NULL, NULL },
8566 12 { jwin_radio_proc, 68, 44, 64, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "Dungeon Carving", NULL, NULL },
8567 12 { jwin_button_proc, 10, 66, 61, 21, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
8568 12 { jwin_button_proc, 90, 66, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
8569 12 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
8570 12 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
8571 };
8572
8573 void draw_tile_list_window()
8574 {
8575 int32_t w = 640;
8576 int32_t h = 480;
8577
8578 int32_t window_xofs=(zq_screen_w-w-12)>>1;
8579 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
8580 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
8581 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
8582
8583 FONT *oldfont = font;
8584 font = get_zc_font(font_lfont);
8585 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Tile", true);
8586 font=oldfont;
8587 return;
8588 }
8589
8590 void show_blank_tile(int32_t t)
8591 {
8592 char tbuf[80], tbuf2[80], tbuf3[80];
8593 sprintf(tbuf, "Tile is%s blank.", blank_tile_table[t]?"":" not");
8594 sprintf(tbuf2, "%c %c", blank_tile_quarters_table[t*4]?'X':'-', blank_tile_quarters_table[(t*4)+1]?'X':'-');
8595 sprintf(tbuf3, "%c %c", blank_tile_quarters_table[(t*4)+2]?'X':'-', blank_tile_quarters_table[(t*4)+3]?'X':'-');
8596 jwin_alert("Blank Tile Information",tbuf,tbuf2,tbuf3,"&OK",NULL,13,27,get_zc_font(font_lfont));
8597 }
8598
8599 static void do_convert_tile(int32_t tile, int32_t tile2, int32_t cs, bool rect_sel, int format, bool shift, bool alt, bool skip_prompt = false)
8600 {
8601 int num_bits;
8602 if (format == tf4Bit)
8603 num_bits = 4;
8604 else if (format == tf8Bit)
8605 num_bits = 8;
8606 else assert(false);
8607
8608 char buf[80];
8609 sprintf(buf, "Do you want to convert the selected %s to %d-bit color?", tile==tile2?"tile":"tiles",num_bits);
8610
8611 if (skip_prompt || jwin_alert("Convert Tile?",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8612 {
8613 go_tiles();
8614 saved=false;
8615
8616 if(format == tf4Bit)
8617 {
8618 memset(cset_reduce_table, 0, 256);
8619 memset(col_diff,0,3*128);
8620 calc_cset_reduce_table(RAMpal, cs);
8621 }
8622
8623 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8624
8625 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8626 {
8627 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8628 firsttile-=coldiff;
8629 lasttile+=coldiff;
8630 }
8631
8632 for(int32_t t=firsttile; t<=lasttile; t++)
8633 if(!rect_sel ||
8634 ((TILECOL(t)>=TILECOL(firsttile)) &&
8635 (TILECOL(t)<=TILECOL(lasttile))))
8636 convert_tile(t, format, cs, shift, alt);
8637
8638 tile=tile2=zc_min(tile,tile2);
8639 }
8640 }
8641
8642
8643 int32_t readtilefile(PACKFILE *f)
8644 {
8645 dword section_version=0;
8646 int32_t zversion = 0;
8647 int32_t zbuild = 0;
8648
8649 if(!p_igetl(&zversion,f))
8650 {
8651 return 0;
8652 }
8653 if(!p_igetl(&zbuild,f))
8654 {
8655 return 0;
8656 }
8657 if(!p_igetw(&section_version,f))
8658 {
8659 return 0;
8660 }
8661 if(!read_deprecated_section_cversion(f))
8662 {
8663 return 0;
8664 }
8665 al_trace("readoneweapon section_version: %d\n", section_version);
8666
8667 if ( zversion > ZELDA_VERSION )
8668 {
8669 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8670 return 0;
8671 }
8672
8673 else if ( ( section_version > V_TILES ))
8674 {
8675 al_trace("Cannot read .ztile packfile made using V_TILES (%d)\n", section_version);
8676 return 0;
8677
8678 }
8679 else
8680 {
8681 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8682 }
8683
8684 int32_t index = 0;
8685 int32_t count = 0;
8686
8687 //tile id
8688 if(!p_igetl(&index,f))
8689 {
8690 return 0;
8691 }
8692 al_trace("Reading tile: index(%d)\n", index);
8693
8694 //tile count
8695 if(!p_igetl(&count,f))
8696 {
8697 return 0;
8698 }
8699 al_trace("Reading tile: count(%d)\n", count);
8700
8701
8702
8703
8704 for ( int32_t tilect = 0; tilect < count; tilect++ )
8705 {
8706 byte *temp_tile = new byte[tilesize(tf32Bit)];
8707 byte format=tf4Bit;
8708 memset(temp_tile, 0, tilesize(tf32Bit));
8709 if(!p_getc(&format,f))
8710 {
8711 delete[] temp_tile;
8712 return 0;
8713 }
8714
8715
8716 if(!pfread(temp_tile,tilesize(format),f))
8717 {
8718 delete[] temp_tile;
8719 return 0;
8720 }
8721
8722 reset_tile(newtilebuf, index+(tilect), format);
8723 memcpy(newtilebuf[index+(tilect)].data,temp_tile,tilesize(newtilebuf[index+(tilect)].format));
8724 delete[] temp_tile;
8725 }
8726
8727
8728 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8729
8730 register_blank_tiles();
8731 register_used_tiles();
8732
8733 return 1;
8734
8735 }
8736
8737 int32_t readtilefile_to_location(PACKFILE *f, int32_t start, int32_t skip)
8738 {
8739 dword section_version=0;
8740 int32_t zversion = 0;
8741 int32_t zbuild = 0;
8742
8743 if(!p_igetl(&zversion,f))
8744 {
8745 return 0;
8746 }
8747 if(!p_igetl(&zbuild,f))
8748 {
8749 return 0;
8750 }
8751 if(!p_igetw(&section_version,f))
8752 {
8753 return 0;
8754 }
8755 if(!read_deprecated_section_cversion(f))
8756 {
8757 return 0;
8758 }
8759 al_trace("readoneweapon section_version: %d\n", section_version);
8760
8761 if ( zversion > ZELDA_VERSION )
8762 {
8763 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8764 return 0;
8765 }
8766
8767 else if ( ( section_version > V_TILES ))
8768 {
8769 al_trace("Cannot read .ztile packfile made using V_TILES (%d)\n", section_version);
8770 return 0;
8771
8772 }
8773 else
8774 {
8775 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8776 }
8777
8778 int32_t index = 0;
8779 int32_t count = 0;
8780
8781 //tile id
8782 if(!p_igetl(&index,f))
8783 {
8784 return 0;
8785 }
8786 al_trace("Reading tile: index(%d)\n", index);
8787
8788 //tile count
8789 if(!p_igetl(&count,f))
8790 {
8791 return 0;
8792 }
8793 al_trace("Reading tile: count(%d)\n", count);
8794
8795
8796 for ( int32_t tilect = 0; tilect < count; tilect++ )
8797 {
8798 byte *temp_tile = new byte[tilesize(tf32Bit)];
8799 byte format=tf4Bit;
8800 memset(temp_tile, 0, tilesize(tf32Bit));
8801 if(!p_getc(&format,f))
8802 {
8803 delete[] temp_tile;
8804 return 0;
8805 }
8806
8807
8808 if(!pfread(temp_tile,tilesize(format),f))
8809 {
8810 delete[] temp_tile;
8811 return 0;
8812 }
8813
8814 reset_tile(newtilebuf, start+(tilect), format);
8815 if ( skip )
8816 {
8817 if ( (start+(tilect)) < skip )
8818 {
8819 delete[] temp_tile;
8820 continue;
8821 }
8822
8823 }
8824 if ( start+(tilect) < NEWMAXTILES )
8825 {
8826 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8827 }
8828 delete[] temp_tile;
8829
8830 }
8831
8832
8833 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8834
8835 register_blank_tiles();
8836 register_used_tiles();
8837
8838 return 1;
8839
8840 }
8841
8842
8843 int32_t readtilefile_to_location(PACKFILE *f, int32_t start)
8844 {
8845 dword section_version=0;
8846 int32_t zversion = 0;
8847 int32_t zbuild = 0;
8848
8849 if(!p_igetl(&zversion,f))
8850 {
8851 return 0;
8852 }
8853 if(!p_igetl(&zbuild,f))
8854 {
8855 return 0;
8856 }
8857 if(!p_igetw(&section_version,f))
8858 {
8859 return 0;
8860 }
8861 if(!read_deprecated_section_cversion(f))
8862 {
8863 return 0;
8864 }
8865 al_trace("readoneweapon section_version: %d\n", section_version);
8866
8867 if ( zversion > ZELDA_VERSION )
8868 {
8869 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8870 return 0;
8871 }
8872
8873 else if ( ( section_version > V_TILES ))
8874 {
8875 al_trace("Cannot read .ztile packfile made using V_TILES (%d)\n", section_version);
8876 return 0;
8877
8878 }
8879 else
8880 {
8881 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8882 }
8883
8884 int32_t index = 0;
8885 int32_t count = 0;
8886
8887 //tile id
8888 if(!p_igetl(&index,f))
8889 {
8890 return 0;
8891 }
8892 al_trace("Reading tile: index(%d)\n", index);
8893
8894 //tile count
8895 if(!p_igetl(&count,f))
8896 {
8897 return 0;
8898 }
8899 al_trace("Reading tile: count(%d)\n", count);
8900
8901
8902
8903
8904 for ( int32_t tilect = 0; tilect < count; tilect++ )
8905 {
8906 byte *temp_tile = new byte[tilesize(tf32Bit)];
8907 byte format=tf4Bit;
8908 memset(temp_tile, 0, tilesize(tf32Bit));
8909
8910 if(!p_getc(&format,f))
8911 {
8912 delete[] temp_tile;
8913 return 0;
8914 }
8915
8916
8917 if(!pfread(temp_tile,tilesize(format),f))
8918 {
8919 delete[] temp_tile;
8920 return 0;
8921 }
8922
8923 reset_tile(newtilebuf, start+(tilect), format);
8924 if ( start+(tilect) < NEWMAXTILES )
8925 {
8926 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8927 }
8928 delete[] temp_tile;
8929 }
8930
8931
8932 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8933
8934 register_blank_tiles();
8935 register_used_tiles();
8936
8937 return 1;
8938
8939 }
8940 int32_t writetilefile(PACKFILE *f, int32_t index, int32_t count)
8941 {
8942 dword section_version=V_TILES;
8943 int32_t zversion = ZELDA_VERSION;
8944 int32_t zbuild = VERSION_BUILD;
8945
8946 if(!p_iputl(zversion,f))
8947 {
8948 return 0;
8949 }
8950 if(!p_iputl(zbuild,f))
8951 {
8952 return 0;
8953 }
8954 if(!p_iputw(section_version,f))
8955 {
8956 return 0;
8957 }
8958
8959 if(!write_deprecated_section_cversion(section_version,f))
8960 {
8961 return 0;
8962 }
8963
8964 //start tile id
8965 if(!p_iputl(index,f))
8966 {
8967 return 0;
8968 }
8969
8970 //count
8971 if(!p_iputl(count,f))
8972 {
8973 return 0;
8974 }
8975
8976 for ( int32_t tilect = 0; tilect < count; tilect++ )
8977 {
8978 if(!p_putc(newtilebuf[index+(tilect)].format,f))
8979 {
8980 return 0;
8981 }
8982 if(!pfwrite(newtilebuf[index+(tilect)].data,tilesize(newtilebuf[index+(tilect)].format),f))
8983 {
8984 return 0;
8985 }
8986 }
8987
8988 return 1;
8989
8990 }
8991
8992 static int32_t _selected_tile=-1, _selected_tcset=-1;
8993 int32_t select_tile(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
8994 {
8995 popup_zqdialog_start();
8996 reset_combo_animations();
8997 reset_combo_animations2();
8998 bound(tile,0,NEWMAXTILES-1);
8999 ex=exnow;
9000 int32_t done=0;
9001 int32_t oflip=flip;
9002 int32_t otile=tile;
9003 int32_t ocs=cs;
9004 int32_t first=(tile/TILES_PER_PAGE)*TILES_PER_PAGE; //first tile on the current page
9005 int32_t copy=-1;
9006 int32_t tile2=tile,copycnt=0;
9007 reftile = 0;
9008 int32_t tile_clicked=-1;
9009 bool rect_sel=true;
9010 bound(first,0,(TILES_PER_PAGE*TILE_PAGES)-1);
9011 position_mouse_z(0);
9012
9013 go();
9014
9015 register_used_tiles();
9016 int32_t w = 640;
9017 int32_t h = 480;
9018 int32_t window_xofs=(zq_screen_w-w-12)>>1;
9019 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
9020 int32_t screen_xofs=window_xofs+6;
9021 int32_t screen_yofs=window_yofs+25;
9022 int32_t panel_yofs=3;
9023 int32_t mul = 2;
9024 FONT *tfont = get_zc_font(font_lfont_l);
9025
9026 draw_tile_list_window();
9027 int32_t f=0;
9028 draw_tiles(first,cs,f);
9029
9030 if(type==0)
9031 {
9032 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
9033 }
9034 else
9035 {
9036 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
9037 }
9038
9039 go_tiles();
9040
9041 while(gui_mouse_b())
9042 {
9043 /* do nothing */
9044 rest(1);
9045 }
9046
9047 bool bdown=false;
9048
9049 #define FOREACH_START(_t) \
9050 { \
9051 int32_t _first, _last; \
9052 if(is_rect) \
9053 { \
9054 _first=top*TILES_PER_ROW+left; \
9055 _last=_first+rows*TILES_PER_ROW|+columns-1; \
9056 } \
9057 else \
9058 { \
9059 _first=zc_min(tile, tile2); \
9060 _last=zc_max(tile, tile2); \
9061 } \
9062 for(int32_t _t=_first; _t<=_last; _t++) \
9063 { \
9064 if(is_rect) \
9065 { \
9066 int32_t row=TILEROW(_t); \
9067 if(row<top || row>=top+rows) \
9068 continue; \
9069 int32_t col=TILECOL(_t); \
9070 if(col<left || col>=left+columns) \
9071 continue; \
9072 } \
9073
9074 #define FOREACH_END\
9075 } \
9076 }
9077
9078 bool did_snap = false;
9079 int otl = tile, otl2 = tile2;
9080 do
9081 {
9082 HANDLE_CLOSE_ZQDLG();
9083 if(exiting_program) break;
9084 rest(4);
9085 int32_t top=TILEROW(zc_min(tile, tile2));
9086 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
9087 int32_t rows=TILEROW(zc_max(tile, tile2))-top+1;
9088 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
9089 bool is_rect=(rows==1)||(columns==TILES_PER_ROW)||rect_sel;
9090 bool redraw=false;
9091
9092 if(mouse_z!=0)
9093 {
9094 sel_tile(tile,tile2,first,type,((mouse_z/abs(mouse_z))*(-1)*TILES_PER_PAGE));
9095 position_mouse_z(0);
9096 redraw=true;
9097 }
9098
9099 if(keypressed())
9100 {
9101 switch(readkey()>>8)
9102 {
9103 case KEY_ENTER_PAD:
9104 case KEY_ENTER:
9105 done=2;
9106 break;
9107
9108 case KEY_ESC:
9109 done=1;
9110 break;
9111
9112 case KEY_F1:
9113 onHelp();
9114 break;
9115
9116 case KEY_EQUALS:
9117 case KEY_PLUS_PAD:
9118 {
9119 if(CHECK_CTRL_CMD ||
9120 key[KEY_ALT] || key[KEY_ALTGR])
9121 {
9122 FOREACH_START(t)
9123 if(key[KEY_ALT] || key[KEY_ALTGR])
9124 shift_tile_colors(t, 16, false);
9125 else
9126 shift_tile_colors(t, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9127 FOREACH_END
9128
9129 register_blank_tiles();
9130 }
9131 else if(edit_cs)
9132 cs = (cs<13) ? cs+1:0;
9133
9134 redraw=true;
9135 break;
9136 }
9137
9138 case KEY_Z:
9139 case KEY_F12:
9140 {
9141 if(!did_snap)
9142 {
9143 //Export tile page as screenshot
9144 PALETTE temppal;
9145 get_palette(temppal);
9146 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
9147 draw_tiles(tempbmp,first,cs,f,false,true);
9148 save_bitmap(getSnapName(), tempbmp, RAMpal);
9149 destroy_bitmap(tempbmp);
9150
9151 redraw = true;
9152 did_snap = true;
9153 }
9154 break;
9155 }
9156
9157 case KEY_S:
9158 {
9159 if(!prompt_for_new_file_compat("Save ZTILE(.ztile)", "ztile", NULL,datapath,false))
9160 break;
9161 PACKFILE *f=pack_fopen_password(temppath,F_WRITE, "");
9162 if(!f) break;
9163 al_trace("Saving tile: %d\n", tile);
9164 writetilefile(f,tile,1);
9165 pack_fclose(f);
9166 break;
9167 }
9168 case KEY_L:
9169 {
9170 if(!prompt_for_existing_file_compat("Load ZTILE(.ztile)", "ztile", NULL,datapath,false))
9171 break;
9172 PACKFILE *f=pack_fopen_password(temppath,F_READ, "");
9173 if(!f) break;
9174 al_trace("Saving tile: %d\n", tile);
9175 if (!readtilefile(f))
9176 {
9177 al_trace("Could not read from .ztile packfile %s\n", temppath);
9178 jwin_alert("ZTILE File: Error","Could not load the specified Tile.",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9179 }
9180 else
9181 {
9182 jwin_alert("ZTILE File: Success!","Loaded the source tiles to your tile sheets!",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9183 }
9184
9185 pack_fclose(f);
9186 //register_blank_tiles();
9187 //register_used_tiles();
9188 redraw=true;
9189 break;
9190 }
9191 case KEY_MINUS:
9192 case KEY_MINUS_PAD:
9193 {
9194 if(CHECK_CTRL_CMD ||
9195 key[KEY_ALT] || key[KEY_ALTGR])
9196 {
9197 FOREACH_START(t)
9198 if(key[KEY_ALT] || key[KEY_ALTGR])
9199 shift_tile_colors(t, -16, false);
9200 else
9201 shift_tile_colors(t, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9202 FOREACH_END
9203
9204 register_blank_tiles();
9205 }
9206 else if(edit_cs)
9207 cs = (cs>0) ? cs-1:13;
9208
9209 redraw=true;
9210 break;
9211 }
9212
9213 case KEY_UP:
9214 {
9215 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9216 {
9217 case 3: //ALT and CTRL
9218 case 2: //ALT
9219 if(is_rect)
9220 {
9221 saved=false;
9222 go_slide_tiles(columns, rows, top, left);
9223 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9224 bool same = true;
9225
9226 for(int32_t d=0; d<columns; d++)
9227 {
9228 for(int32_t s=0; s<rows; s++)
9229 {
9230 int32_t t=((top+s)*TILES_PER_ROW)+left+d;
9231
9232 if(newtilebuf[t].format!=bitcheck) same = false;
9233 }
9234 }
9235
9236 if(!same) break;
9237
9238 // This used to do something. Too lazy to remove.
9239 // Can probably remove the above "same" check too.
9240 bitcheck = 2;
9241
9242 for(int32_t c=0; c<columns; c++)
9243 {
9244 for(int32_t r=0; r<rows; r++)
9245 {
9246 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9247 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(8*bitcheck));
9248 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data);
9249
9250 for(int32_t pixelrow=0; pixelrow<16*bitcheck; pixelrow++)
9251 {
9252 if(pixelrow==15*bitcheck)
9253 {
9254 int32_t srctile=temptile+TILES_PER_ROW;
9255 if(srctile>=NEWMAXTILES)
9256 srctile-=rows*TILES_PER_ROW;
9257 src_pixelrow=(qword*)(newtilebuf[srctile].data);
9258 }
9259
9260 *dest_pixelrow=*src_pixelrow;
9261 dest_pixelrow++;
9262 src_pixelrow++;
9263 }
9264 }
9265
9266 qword *dest_pixelrow=(qword*)(newtilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9267
9268 for(int32_t b=0; b<bitcheck; b++,dest_pixelrow++)
9269 {
9270 if((CHECK_CTRL_CMD))
9271 {
9272 *dest_pixelrow=0;
9273 }
9274 else
9275 {
9276 qword *src_pixelrow=(qword*)(newundotilebuf[(top*TILES_PER_ROW)+left+c].data+(8*b));
9277 *dest_pixelrow=*src_pixelrow;
9278 }
9279 }
9280 }
9281 }
9282
9283 register_blank_tiles();
9284 redraw=true;
9285 break;
9286
9287 case 1: //CTRL
9288 case 0: //None
9289 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(tile_page_row(tile)*TILES_PER_ROW):-TILES_PER_ROW);
9290 redraw=true;
9291
9292 default: //Others
9293 break;
9294 }
9295 }
9296 break;
9297
9298 case KEY_DOWN:
9299 {
9300 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9301 {
9302 case 3: //ALT and CTRL
9303 case 2: //ALT
9304 if(is_rect)
9305 {
9306 saved=false;
9307 go_slide_tiles(columns, rows, top, left);
9308 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9309 bool same = true;
9310
9311 for(int32_t c=0; c<columns; c++)
9312 {
9313 for(int32_t r=0; r<rows; r++)
9314 {
9315 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9316
9317 if(newtilebuf[t].format!=bitcheck) same = false;
9318 }
9319 }
9320
9321 if(!same) break;
9322
9323 // This used to do something. Too lazy to remove.
9324 // Can probably remove the above "same" check too.
9325 bitcheck = 2;
9326
9327 for(int32_t c=0; c<columns; c++)
9328 {
9329 for(int32_t r=rows-1; r>=0; r--)
9330 {
9331 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9332 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(112*bitcheck)+(8*(bitcheck-1)));
9333 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data+(120*bitcheck)+(8*(bitcheck-1)));
9334
9335 for(int32_t pixelrow=(8<<bitcheck)-1; pixelrow>=0; pixelrow--)
9336 {
9337 if(pixelrow<bitcheck)
9338 {
9339 int32_t srctile=temptile-TILES_PER_ROW;
9340 if(srctile<0)
9341 srctile+=rows*TILES_PER_ROW;
9342 qword *tempsrc=(qword*)(newtilebuf[srctile].data+(120*bitcheck)+(8*pixelrow));
9343 *dest_pixelrow=*tempsrc;
9344 //*dest_pixelrow=0;
9345 }
9346 else
9347 {
9348 *dest_pixelrow=*src_pixelrow;
9349 }
9350
9351 dest_pixelrow--;
9352 src_pixelrow--;
9353 }
9354 }
9355
9356 qword *dest_pixelrow=(qword*)(newtilebuf[(top*TILES_PER_ROW)+left+c].data);
9357 qword *src_pixelrow=(qword*)(newundotilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9358
9359 for(int32_t b=0; b<bitcheck; b++)
9360 {
9361 if((CHECK_CTRL_CMD))
9362 {
9363 *dest_pixelrow=0;
9364 }
9365 else
9366 {
9367 *dest_pixelrow=*src_pixelrow;
9368 }
9369
9370 dest_pixelrow++;
9371 src_pixelrow++;
9372 }
9373 }
9374 }
9375
9376 register_blank_tiles();
9377 redraw=true;
9378 break;
9379
9380 case 1: //CTRL
9381 case 0: //None
9382 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_ROWS_PER_PAGE-1)-tile_page_row(tile))*TILES_PER_ROW:TILES_PER_ROW);
9383 redraw=true;
9384
9385 default: //Others
9386 break;
9387 }
9388 }
9389 break;
9390
9391 case KEY_LEFT:
9392 {
9393 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9394 {
9395 case 3: //ALT and CTRL
9396 case 2: //ALT
9397 if(is_rect)
9398 {
9399 saved=false;
9400 go_slide_tiles(columns, rows, top, left);
9401 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9402 bool same = true;
9403
9404 for(int32_t c=0; c<columns; c++)
9405 {
9406 for(int32_t r=0; r<rows; r++)
9407 {
9408 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9409
9410 if(newtilebuf[t].format!=bitcheck) same = false;
9411 }
9412 }
9413
9414 if(!same) break;
9415
9416 // This used to do something. Too lazy to remove.
9417 // Can probably remove the above "same" check too.
9418 bitcheck = 2;
9419
9420 for(int32_t r=0; r<rows; r++)
9421 {
9422 for(int32_t c=0; c<columns; c++)
9423 {
9424 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9425 byte *dest_pixelrow=(newtilebuf[temptile].data);
9426
9427 for(int32_t pixelrow=0; pixelrow<16; pixelrow++)
9428 {
9429 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9430 {
9431 *dest_pixelrow=*(dest_pixelrow+1);
9432 dest_pixelrow++;
9433 }
9434
9435 if(c==columns-1)
9436 {
9437 if(!(CHECK_CTRL_CMD))
9438 {
9439 byte *tempsrc=(newundotilebuf[((top+r)*TILES_PER_ROW)+left].data+(pixelrow*8*bitcheck));
9440 *dest_pixelrow=*tempsrc;
9441 }
9442 }
9443 else
9444
9445 {
9446 byte *tempsrc=(newtilebuf[temptile+1].data+(pixelrow*8*bitcheck));
9447 *dest_pixelrow=*tempsrc;
9448 }
9449
9450 dest_pixelrow++;
9451 }
9452 }
9453 }
9454
9455 register_blank_tiles();
9456 redraw=true;
9457 }
9458
9459 break;
9460
9461 case 1: //CTRL
9462 case 0: //None
9463 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile%TILES_PER_ROW):-1);
9464 redraw=true;
9465
9466 default: //Others
9467 break;
9468 }
9469 }
9470 break;
9471
9472 case KEY_RIGHT:
9473 {
9474 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9475 {
9476 case 3: //ALT and CTRL
9477 case 2: //ALT
9478 if(is_rect)
9479 {
9480 saved=false;
9481 go_slide_tiles(columns, rows, top, left);
9482 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9483 bool same = true;
9484
9485 for(int32_t c=0; c<columns; c++)
9486 {
9487 for(int32_t r=0; r<rows; r++)
9488 {
9489 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9490
9491 if(newtilebuf[t].format!=bitcheck) same = false;
9492 }
9493 }
9494
9495 if(!same) break;
9496
9497 // This used to do something. Too lazy to remove.
9498 // Can probably remove the above "same" check too.
9499 bitcheck = 2;
9500
9501 for(int32_t r=0; r<rows; r++)
9502 {
9503 for(int32_t c=columns-1; c>=0; c--)
9504 {
9505 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9506 byte *dest_pixelrow=(newtilebuf[temptile].data)+(128*bitcheck)-1;
9507
9508 for(int32_t pixelrow=15; pixelrow>=0; pixelrow--)
9509 {
9510 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9511 {
9512 *dest_pixelrow=*(dest_pixelrow-1);
9513 dest_pixelrow--;
9514 }
9515
9516 if(c==0)
9517 {
9518 if(!(CHECK_CTRL_CMD))
9519 {
9520 byte *tempsrc=(newundotilebuf[(((top+r)*TILES_PER_ROW)+left+columns-1)].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9521 *dest_pixelrow=*tempsrc;
9522 }
9523 }
9524 else
9525 {
9526 byte *tempsrc=(newtilebuf[temptile-1].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9527 *dest_pixelrow=*tempsrc;
9528 }
9529
9530 dest_pixelrow--;
9531 }
9532 }
9533 }
9534
9535 register_blank_tiles();
9536 redraw=true;
9537 }
9538
9539 break;
9540
9541 case 1: //CTRL
9542 case 0: //None
9543 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILES_PER_ROW)-(tile%TILES_PER_ROW)-1:1);
9544 redraw=true;
9545
9546 default: //Others
9547 break;
9548 }
9549 }
9550 break;
9551
9552 case KEY_PGUP:
9553 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(TILEROW(tile)*TILES_PER_ROW):-TILES_PER_PAGE);
9554 redraw=true;
9555 break;
9556
9557 case KEY_PGDN:
9558 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_PAGES*TILE_ROWS_PER_PAGE)-TILEROW(tile)-1)*TILES_PER_ROW:TILES_PER_PAGE);
9559 redraw=true;
9560 break;
9561
9562 case KEY_HOME:
9563 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile):-(tile%TILES_PER_PAGE));
9564 redraw=true;
9565 break;
9566
9567 case KEY_END:
9568 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILE_PAGES)*(TILES_PER_PAGE)-tile-1:(TILES_PER_PAGE)-(tile%TILES_PER_PAGE)-1);
9569 redraw=true;
9570 break;
9571
9572 case KEY_P:
9573 {
9574 int32_t whatPage = gettilepagenumber("Goto Page", (PreFillTileEditorPage?(first/TILES_PER_PAGE):0));
9575
9576 if(whatPage >= 0)
9577 sel_tile(tile,tile2,first,type,((whatPage-TILEPAGE(tile))*TILE_ROWS_PER_PAGE)*TILES_PER_ROW);
9578
9579 break;
9580 }
9581
9582 case KEY_O:
9583 if(type==0 && copy>=0)
9584 {
9585 go_tiles();
9586
9587 if(key[KEY_LSHIFT] ||key[KEY_RSHIFT])
9588 {
9589 mass_overlay_tile(zc_min(tile,tile2),zc_max(tile,tile2),copy,cs,(CHECK_CTRL_CMD), rect_sel);
9590 saved=false;
9591 }
9592 else
9593 {
9594 saved = !overlay_tiles(tile,tile2,copy,copycnt,rect_sel,false,cs,(CHECK_CTRL_CMD));
9595 //overlay_tile(newtilebuf,tile,copy,cs,(CHECK_CTRL_CMD));
9596 }
9597
9598 saved=false;
9599 redraw=true;
9600 }
9601
9602 break;
9603
9604 case KEY_E:
9605 if(type==0)
9606 {
9607 edit_tile(tile,flip,cs);
9608 draw_tile_list_window();
9609 redraw=true;
9610 }
9611
9612 break;
9613
9614 case KEY_G:
9615 if(type==0)
9616 {
9617 grab_tile(tile,cs);
9618 draw_tile_list_window();
9619 redraw=true;
9620 }
9621
9622 break;
9623
9624 case KEY_C:
9625 copy=zc_min(tile,tile2);
9626 copycnt=abs(tile-tile2)+1;
9627 redraw=true;
9628 break;
9629
9630 case KEY_X:
9631 if(type==2)
9632 {
9633 ex=(ex+1)%3;
9634 }
9635
9636 break;
9637
9638 case KEY_R:
9639 if(type==2)
9640 break;
9641 if(type==1)
9642 {
9643 flip = rotate_value(flip);
9644 redraw=true;
9645 break;
9646 }
9647
9648 go_tiles();
9649
9650 if(CHECK_CTRL_CMD)
9651 {
9652 bool go=false;
9653 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
9654 go=true;
9655 else if(massRecolorSetup(cs))
9656 go=true;
9657
9658 if(go)
9659 {
9660 FOREACH_START(t)
9661 massRecolorApply(t);
9662 FOREACH_END
9663
9664 register_blank_tiles();
9665 }
9666 }
9667 else
9668 {
9669 FOREACH_START(t)
9670 rotate_tile(t,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
9671 FOREACH_END
9672 }
9673
9674 redraw=true;
9675 saved=false;
9676 break;
9677
9678 case KEY_SPACE:
9679 rect_sel=!rect_sel;
9680 copy=-1;
9681 redraw=true;
9682 break;
9683
9684 case KEY_H:
9685 flip^=1;
9686 go_tiles();
9687
9688 if(type==0)
9689 {
9690 normalize(tile,tile2,rect_sel,flip);
9691 flip=0;
9692 }
9693
9694 redraw=true;
9695 break;
9696
9697
9698 case KEY_V:
9699 if(copy==-1)
9700 {
9701 if(type!=2)
9702 {
9703 flip^=2;
9704 go_tiles();
9705
9706 if(type==0)
9707 {
9708 normalize(tile,tile2,rect_sel,flip);
9709 flip=0;
9710 }
9711 }
9712 }
9713 else
9714 {
9715 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9716 go_tiles();
9717 saved = !copy_tiles(tile,tile2,copy,copycnt,rect_sel,false);
9718 }
9719
9720 redraw=true;
9721 break;
9722
9723 case KEY_F:
9724 if(copy==-1)
9725 {
9726 break;
9727 }
9728 else
9729 {
9730 go_tiles();
9731 {
9732 saved = !copy_tiles_floodfill(tile,tile2,copy,copycnt,rect_sel,false);
9733 }
9734 }
9735
9736 redraw=true;
9737 break;
9738
9739 case KEY_DEL:
9740 if(type==0 && (key[KEY_LSHIFT]||key[KEY_RSHIFT]))
9741 {
9742 bool warn = (rect_sel
9743 && ((tile/20)!=(tile2/20))
9744 && !(tile%20==0&&tile2%20==19));
9745 int32_t z=zc_min(tile,tile2);
9746 int32_t count = abs(tile-tile2) + 1;
9747 tile=z;
9748 tile2=NEWMAXTILES;
9749 copy = tile + count;
9750 copycnt = NEWMAXTILES-copy;
9751 char buf[64];
9752
9753 if(count>1)
9754 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9755 else
9756 sprintf(buf,"Remove tile %d?",tile);
9757
9758 AlertDialog("Remove Tiles", std::string(buf)
9759 +"\nThis will offset the tiles that follow!"
9760 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9761 [&](bool ret,bool)
9762 {
9763 if(ret)
9764 {
9765 go_tiles();
9766 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9767 {
9768 redraw=true;
9769 saved=false;
9770 }
9771 }
9772 }).show();
9773 }
9774 delete_tiles(tile,tile2,rect_sel);
9775 redraw=true;
9776 break;
9777
9778 case KEY_U:
9779 {
9780 if(CHECK_CTRL_CMD)
9781 {
9782 //Only toggle the first 2 bits!
9783 show_only_unused_tiles = (show_only_unused_tiles&~3) | (((show_only_unused_tiles&3)+1)%4);
9784 }
9785 else
9786 {
9787 comeback_tiles();
9788 }
9789
9790 redraw=true;
9791 }
9792 break;
9793
9794 case KEY_8:
9795 case KEY_8_PAD:
9796 hide_8bit_marker();
9797 break;
9798
9799 case KEY_I: //insert tiles
9800 if(type==0)
9801 {
9802 bool warn = (rect_sel
9803 && ((tile/20)!=(tile2/20))
9804 && !(tile%20==0&&tile2%20==19));
9805 int32_t z=zc_min(tile,tile2);
9806 int32_t count = abs(tile-tile2) + 1;
9807 tile=z;
9808 tile2=NEWMAXTILES;
9809 copy = tile + count;
9810 copycnt = NEWMAXTILES-copy;
9811
9812 if(key[KEY_LSHIFT]||key[KEY_RSHIFT]) //Remove
9813 {
9814 char buf[64];
9815
9816 if(count>1)
9817 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9818 else
9819 sprintf(buf,"Remove tile %d?",tile);
9820
9821 AlertDialog("Remove Tiles", std::string(buf)
9822 +"\nThis will offset the tiles that follow!"
9823 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9824 [&](bool ret,bool)
9825 {
9826 if(ret)
9827 {
9828 go_tiles();
9829 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9830 {
9831 redraw=true;
9832 saved=false;
9833 }
9834 }
9835 }).show();
9836 }
9837 else
9838 {
9839 char buf[64];
9840
9841 if(count>1)
9842 sprintf(buf,"Insert %d blank tiles?",count);
9843 else
9844 sprintf(buf,"Insert a blank tile?");
9845
9846 AlertDialog("Insert Tiles", std::string(buf)
9847 +"\nThis will offset the tiles that follow!"
9848 +(warn?"\nInserting tiles ignores rectangular selections!":""),
9849 [&](bool ret,bool)
9850 {
9851 if(ret)
9852 {
9853 go_tiles();
9854 if(copy_tiles(copy,tile2,tile,copycnt,false,true))
9855 {
9856 redraw=true;
9857 saved=false;
9858 }
9859 }
9860 }).show();
9861 }
9862
9863 copy=-1;
9864 tile2=tile=z;
9865 }
9866 break;
9867 case KEY_M:
9868 if(type==0)
9869 {
9870 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
9871 {
9872 go_tiles();
9873 if(copy_tiles(tile,tile2,copy,copycnt,rect_sel,true))
9874 saved=false;
9875 }
9876 else if(copy==-1)
9877 {
9878 // I don't know what this was supposed to be doing before.
9879 // It didn't work in anything like a sensible way.
9880 if(rect_sel)
9881 {
9882 make_combos_rect(top, left, rows, columns, cs);
9883 }
9884 else
9885 {
9886 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
9887 }
9888 }
9889
9890 redraw=true;
9891 }
9892 break;
9893
9894 case KEY_D:
9895 {
9896 int32_t frames=1;
9897 char buf[80];
9898 sprintf(buf, "%d", frames);
9899 create_relational_tiles_dlg[0].dp2=get_zc_font(font_lfont);
9900 create_relational_tiles_dlg[2].dp=buf;
9901
9902 large_dialog(create_relational_tiles_dlg);
9903
9904 int32_t ret=do_zqdialog(create_relational_tiles_dlg,2);
9905
9906 if(ret==5)
9907 {
9908 frames=zc_max(atoi(buf),1);
9909 bool same = true;
9910 int32_t bitcheck=newtilebuf[tile].format;
9911
9912 for(int32_t t=1; t<frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); ++t)
9913 {
9914 if(newtilebuf[tile+t].format!=bitcheck) same = false;
9915 }
9916
9917 if(!same)
9918 {
9919 jwin_alert("Error","The source tiles are not","in the same format.",NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9920 break;
9921 }
9922
9923 if(tile+(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96))>NEWMAXTILES)
9924 {
9925 jwin_alert("Error","Too many tiles will be created",NULL,NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9926 break;
9927 }
9928
9929 for(int32_t i=frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); i<(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96)); ++i)
9930 {
9931 reset_tile(newtilebuf, tile+i, bitcheck);
9932 }
9933
9934 if(create_relational_tiles_dlg[3].flags&D_SELECTED)
9935 {
9936 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9937 {
9938 for(int32_t j=0; j<frames; ++j)
9939 {
9940 merge_tiles(tile+(i*frames)+j, (tile+(relational_template[i][0]*frames)+j)<<2, ((tile+(relational_template[i][1]*frames)+j)<<2)+1, ((tile+(relational_template[i][2]*frames)+j)<<2)+2, ((tile+(relational_template[i][3]*frames)+j)<<2)+3);
9941 }
9942 }
9943 }
9944 else
9945 {
9946 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9947 {
9948 for(int32_t j=0; j<frames; ++j)
9949 {
9950 merge_tiles(tile+(i*frames)+j, (tile+(dungeon_carving_template[i][0]*frames)+j)<<2, ((tile+(dungeon_carving_template[i][1]*frames)+j)<<2)+1, ((tile+(dungeon_carving_template[i][2]*frames)+j)<<2)+2, ((tile+(dungeon_carving_template[i][3]*frames)+j)<<2)+3);
9951 }
9952 }
9953 }
9954 }
9955 register_blank_tiles();
9956 register_used_tiles();
9957 redraw=true;
9958 saved=false;
9959 break;
9960 }
9961
9962 case KEY_B:
9963 {
9964 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9965 bool control=(CHECK_CTRL_CMD);
9966 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9967 int format = control ? tf4Bit : tf8Bit;
9968
9969 do_convert_tile(tile, tile2, cs, rect_sel, format, shift, alt);
9970 register_blank_tiles();
9971 }
9972 break;
9973 }
9974
9975 clear_keybuf();
9976 }
9977
9978 if(!(key[KEY_Z] || key[KEY_F12]))
9979 did_snap = false;
9980
9981 if(gui_mouse_b()&1)
9982 {
9983 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
9984 {
9985 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
9986 {
9987 done=1;
9988 }
9989 }
9990
9991 int32_t x=gui_mouse_x()-screen_xofs;
9992 int32_t y=gui_mouse_y()-screen_yofs;
9993
9994 if(y>=0 && y<208*mul)
9995 {
9996 x=zc_min(zc_max(x,0),(320*mul)-1);
9997 int32_t t = (y>>(5))*TILES_PER_ROW + (x>>(5)) + first;
9998
9999 if(type==0 && (key[KEY_LSHIFT] || key[KEY_RSHIFT]))
10000 {
10001 tile2=t;
10002 }
10003 else
10004 {
10005 tile=tile2=t;
10006 }
10007
10008 if(tile_clicked!=t)
10009 {
10010 dclick_status=DCLICK_NOT;
10011 }
10012 else if(dclick_status == DCLICK_AGAIN)
10013 {
10014 while(gui_mouse_b())
10015 {
10016 /* do nothing */
10017 rest(1);
10018 }
10019
10020 if(((y>>(5))*TILES_PER_ROW + (x>>(5)) + first)!=t)
10021 {
10022 dclick_status=DCLICK_NOT;
10023 }
10024 else
10025 {
10026 if(type==0)
10027 {
10028 edit_tile(tile,flip,cs);
10029 draw_tile_list_window();
10030 redraw=true;
10031 }
10032 else
10033 {
10034 done=2;
10035 }
10036 }
10037 }
10038
10039 tile_clicked=t;
10040 }
10041 else if(x>300*mul && !bdown)
10042 {
10043 if(y<224*mul && first>0)
10044 {
10045 first-=TILES_PER_PAGE;
10046 redraw=true;
10047 }
10048
10049 if(y>=224*mul && first<TILES_PER_PAGE*(TILE_PAGES-1))
10050 {
10051 first+=TILES_PER_PAGE;
10052 redraw=true;
10053 }
10054
10055 bdown=true;
10056 }
10057
10058 if(type==1||type==2)
10059 {
10060 if(!bdown && isinRect(x,y,8*mul,216*mul+panel_yofs,23*mul,231*mul+panel_yofs))
10061 done=1;
10062
10063 if(!bdown && isinRect(x,y,148*mul,216*mul+panel_yofs,163*mul,231*mul+panel_yofs))
10064 done=2;
10065 }
10066 else if(!bdown && isinRect(x,y,127*mul,216*mul+panel_yofs,(127+15)*mul,(216+15)*mul+panel_yofs))
10067 {
10068 rect_sel=!rect_sel;
10069 copy=-1;
10070 redraw=true;
10071 }
10072 else if(!bdown && isinRect(x,y,150*mul,213*mul+panel_yofs,(150+28)*mul,(213+21)*mul+panel_yofs))
10073 {
10074 FONT *tf = font;
10075 font = tfont;
10076
10077 if(do_text_button(150*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Grab"))
10078 {
10079 font = tf;
10080 grab_tile(tile,cs);
10081 draw_tile_list_window();
10082 position_mouse_z(0);
10083 redraw=true;
10084 }
10085
10086 font = tf;
10087 }
10088 else if(!bdown && isinRect(x,y,(150+28)*mul,213*mul+panel_yofs,(150+28*2)*mul,(213+21)*mul+panel_yofs+21))
10089 {
10090 FONT *tf = font;
10091 font = tfont;
10092
10093 if(do_text_button((150+28)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Edit"))
10094 {
10095 font = tf;
10096 edit_tile(tile,flip,cs);
10097 draw_tile_list_window();
10098 redraw=true;
10099 }
10100
10101 font = tf;
10102 }
10103 else if(!bdown && isinRect(x,y,(150+28*2)*mul,213*mul+panel_yofs,(150+28*3)*mul,(213+21)*mul+panel_yofs))
10104 {
10105 FONT *tf = font;
10106 font = tfont;
10107
10108 if(do_text_button((150+28*2)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Export"))
10109 {
10110 std::string initial_path = "tileset.png";
10111 if (strlen(datapath))
10112 initial_path = fmt::format("{}/{}", datapath, initial_path);
10113 if(prompt_for_new_file_compat("Export Tile Page (.png)","png",NULL,initial_path,true))
10114 {
10115 PALETTE temppal;
10116 get_palette(temppal);
10117 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
10118 draw_tiles(tempbmp,first,cs,f,false,true);
10119 save_bitmap(temppath, tempbmp, RAMpal);
10120 destroy_bitmap(tempbmp);
10121 }
10122 }
10123
10124 font = tf;
10125 }
10126 else if(!bdown && isinRect(x,y,(150+28*3)*mul,213*mul+panel_yofs,(150+28*4)*mul,(213+21)*mul+panel_yofs))
10127 {
10128 FONT *tf = font;
10129 font = tfont;
10130
10131 if(do_text_button((150+28*3)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Recolor"))
10132 {
10133 if(massRecolorSetup(cs))
10134 {
10135 go_tiles();
10136
10137 FOREACH_START(t)
10138 massRecolorApply(t);
10139 FOREACH_END
10140
10141 register_blank_tiles();
10142 }
10143 }
10144
10145 font = tf;
10146 }
10147 else if(!bdown && isinRect(x,y,(150+28*4)*mul,213*mul+panel_yofs,(150+28*5)*mul,(213+21)*mul+panel_yofs))
10148 {
10149 FONT *tf = font;
10150 font = tfont;
10151
10152 if(do_text_button((150+28*4)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Done"))
10153 {
10154 done=1;
10155 }
10156
10157 font = tf;
10158 }
10159
10160 bdown=true;
10161 }
10162
10163 bool r_click = false;
10164
10165 if(gui_mouse_b()&2 && !bdown && type==0)
10166 {
10167 int32_t x=(gui_mouse_x()-screen_xofs);//&0xFF0;
10168 int32_t y=(gui_mouse_y()-screen_yofs);//&0xF0;
10169
10170 if(y>=0 && y<208*mul)
10171 {
10172 x=zc_min(zc_max(x,0),(320*mul)-1);
10173 int32_t t = ((y)>>(5))*TILES_PER_ROW + ((x)>>(5)) + first;
10174
10175 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
10176 tile=tile2=t;
10177 }
10178
10179 bdown = r_click = true;
10180 f=8;
10181 }
10182
10183 if(gui_mouse_b()==0)
10184 bdown=false;
10185
10186 position_mouse_z(0);
10187
10188 REDRAW:
10189
10190 if((f%8)==0 || InvalidBG == 1)
10191 redraw=true;
10192 if(otl != tile || otl2 != tile2)
10193 {
10194 otl = tile;
10195 otl2 = tile2;
10196 redraw = true;
10197 }
10198
10199 if(redraw)
10200 {
10201 draw_tiles(first,cs,f);
10202 }
10203 if(f&8)
10204 {
10205 if(rect_sel)
10206 {
10207 for(int32_t i=zc_min(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10208 zc_min(TILECOL(tile),TILECOL(tile2));
10209 i<=zc_max(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10210 zc_max(TILECOL(tile),TILECOL(tile2)); i++)
10211 {
10212 if(i>=first && i<first+TILES_PER_PAGE &&
10213 TILECOL(i)>=zc_min(TILECOL(tile),TILECOL(tile2)) &&
10214 TILECOL(i)<=zc_max(TILECOL(tile),TILECOL(tile2)))
10215 {
10216 int32_t x=TILECOL(i)<<(5);
10217 int32_t y=TILEROW(i-first)<<(5);
10218 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10219 }
10220 }
10221 }
10222 else
10223 {
10224 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
10225 {
10226 if(i>=first && i<first+TILES_PER_PAGE)
10227 {
10228 int32_t x=TILECOL(i)<<(5);
10229 int32_t y=TILEROW(i-first)<<(5);
10230 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10231 }
10232 }
10233 }
10234 }
10235
10236 if(type==0)
10237 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
10238 else
10239 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
10240
10241 if(type==2)
10242 {
10243 char cbuf[16];
10244 sprintf(cbuf, "E&xtend: %s",ex==2 ? "32x32" : ex==1 ? "32x16" : "16x16");
10245 gui_textout_ln(screen, get_zc_font(font_lfont_l), (uint8_t *)cbuf, (235*mul)+screen_xofs, (212*mul)+screen_yofs+panel_yofs, jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
10246 }
10247
10248 ++f;
10249
10250 if(r_click)
10251 {
10252 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_USED, HIDE_USED);
10253 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_UNUSED, HIDE_UNUSED);
10254 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_BLANK, HIDE_BLANK);
10255 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_8BIT, HIDE_8BIT_MARKER);
10256
10257 int current_tile_format = MENUID_SELTILE_COLOR_DEPTH_4_BIT;
10258 if (newtilebuf[tile].format == tf8Bit)
10259 current_tile_format = MENUID_SELTILE_COLOR_DEPTH_8_BIT;
10260 select_tile_color_depth_menu.select_only_uid(current_tile_format);
10261 select_tile_color_depth_cb = [&](int format){
10262 if (newtilebuf[tile].format == format)
10263 return;
10264
10265 bool skip_prompt = true;
10266 do_convert_tile(tile, tile2, cs, rect_sel, format, false, false, skip_prompt);
10267 };
10268
10269 NewMenu rcmenu
10270 {
10271 { "Copy", [&]()
10272 {
10273 copy = zc_min(tile,tile2);
10274 copycnt = abs(tile-tile2)+1;
10275 } },
10276 { "Paste", [&]()
10277 {
10278 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, false);
10279 if(saved) saved = !b;
10280 }, nullopt, copy < 0 ? MFL_DIS : 0 },
10281 { "Move", [&]()
10282 {
10283 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, true);
10284 if(saved) saved = !b;
10285 }, nullopt, copy < 0 ? MFL_DIS : 0 },
10286 { "Clear", [&]()
10287 {
10288 delete_tiles(tile, tile2, rect_sel);
10289 } },
10290 { "Set as Reference", [&]()
10291 {
10292 reftile = tile;
10293 } },
10294 {},
10295 { "Edit", [&]()
10296 {
10297 edit_tile(tile, flip, cs);
10298 draw_tile_list_window();
10299 } },
10300 { "Grab", [&]()
10301 {
10302 grab_tile(tile, cs);
10303 draw_tile_list_window();
10304 position_mouse_z(0);
10305 } },
10306 { "Scale", [&]()
10307 {
10308 bool b = scale_or_rotate_tiles(tile, tile2, cs, false);
10309 if(saved) saved = !b;
10310 }, nullopt, type != 0 ? MFL_DIS : 0 },
10311 { "Angular Rotation", [&]()
10312 {
10313 bool b = scale_or_rotate_tiles(tile, tile2, cs, true);
10314 if(saved) saved = !b;
10315 }, nullopt, type != 0 ? MFL_DIS : 0 },
10316 { "Color Depth", &select_tile_color_depth_menu },
10317 {},
10318 { "Blank?", [&]()
10319 {
10320 show_blank_tile(tile);
10321 } },
10322 {},
10323 { "View ", &select_tile_view_menu },
10324 { "Overlay", [&]()
10325 {
10326 overlay_tile(newtilebuf, tile, copy, cs, 0);
10327 } },
10328 { "H-Flip", [&]()
10329 {
10330 flip ^= 1;
10331 go_tiles();
10332
10333 if(type == 0)
10334 {
10335 normalize(tile, tile2, rect_sel, flip);
10336 flip = 0;
10337 }
10338 } },
10339 { "V-Flip", [&]()
10340 {
10341 flip ^= 2;
10342 go_tiles();
10343
10344 if(type == 0)
10345 {
10346 normalize(tile, tile2, rect_sel, flip);
10347 flip = 0;
10348 }
10349 } },
10350 { "Create Combos", [&]()
10351 {
10352 if(rect_sel)
10353 make_combos_rect(top, left, rows, columns, cs);
10354 else
10355 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
10356 }, nullopt, type != 0 ? MFL_DIS : 0 },
10357 { "Insert", [&]()
10358 {
10359 bool warn = (rect_sel
10360 && ((tile/20)!=(tile2/20))
10361 && !(tile%20==0&&tile2%20==19));
10362 int32_t z = zc_min(tile, tile2);
10363 int32_t count = abs(tile-tile2) + 1;
10364 tile = z;
10365 tile2 = NEWMAXTILES;
10366 copy = tile + count;
10367 copycnt = NEWMAXTILES-copy;
10368
10369 string msg;
10370
10371 if(count>1)
10372 msg = fmt::format("Insert {} blank tiles?",count);
10373 else
10374 msg = "Insert a blank tile?";
10375
10376 AlertDialog("Insert Tiles", msg
10377 +"\nThis will offset the tiles that follow!"
10378 +(warn?"\nInserting tiles ignores rectangular selections!":""),
10379 [&](bool ret,bool)
10380 {
10381 if(ret)
10382 {
10383 go_tiles();
10384 if(copy_tiles(copy, tile2, tile, copycnt, false, true))
10385 saved = false;
10386 }
10387 }).show();
10388
10389 copy=-1;
10390 tile2=tile=z;
10391 }, nullopt, type != 0 ? MFL_DIS : 0 },
10392 { "Remove", [&]()
10393 {
10394 bool warn = (rect_sel
10395 && ((tile/20)!=(tile2/20))
10396 && !(tile%20==0&&tile2%20==19));
10397 int32_t z = zc_min(tile, tile2);
10398 int32_t count = abs(tile-tile2) + 1;
10399 tile = z;
10400 tile2 = NEWMAXTILES;
10401 copy = tile + count;
10402 copycnt = NEWMAXTILES-copy;
10403
10404 string msg;
10405
10406 if(count>1)
10407 msg = fmt::format("Remove tiles {} - {}?", tile, copy-1);
10408 else
10409 msg = fmt::format("Remove tile {}?", tile);
10410
10411 AlertDialog("Remove Tiles", msg
10412 +"\nThis will offset the tiles that follow!"
10413 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
10414 [&](bool ret,bool)
10415 {
10416 if(ret)
10417 {
10418 go_tiles();
10419 if(copy_tiles(tile, tile2, copy, copycnt, false, true))
10420 saved = false;
10421 }
10422 }).show();
10423
10424 copy=-1;
10425 tile2=tile=z;
10426 }, nullopt, type != 0 ? MFL_DIS : 0 },
10427 };
10428 rcmenu.pop(window_mouse_x(),window_mouse_y());
10429 redraw = true;
10430 r_click = false;
10431 goto REDRAW;
10432 }
10433 update_hw_screen();
10434 }
10435 while(!done);
10436
10437 while(gui_mouse_b())
10438 {
10439 /* do nothing */
10440 rest(1);
10441 }
10442
10443 comeback();
10444 register_blank_tiles();
10445 register_used_tiles();
10446 setup_combo_animations();
10447 setup_combo_animations2();
10448 int32_t ret = done-1;
10449 if(ret)
10450 {
10451 _selected_tile = tile;
10452 _selected_tcset = cs;
10453 }
10454
10455 popup_zqdialog_end();
10456 return ret;
10457 }
10458 int32_t select_tile_2(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
10459 {
10460 if(_selected_tile > -1)
10461 {
10462 tile = _selected_tile;
10463 cs = _selected_tcset;
10464 }
10465 int32_t ret = select_tile(tile,flip,type,cs,edit_cs,exnow,always_use_flip);
10466 if(_selected_tile < 0)
10467 {
10468 _selected_tile = tile;
10469 _selected_tcset = cs;
10470 }
10471 return ret;
10472 }
10473
10474 int32_t onTiles()
10475 {
10476 return onGotoTiles(-1);
10477 }
10478
10479 int32_t onGotoTiles(int32_t startfrom)
10480 {
10481 static int32_t t = 0;
10482 if (startfrom > -1)
10483 t = startfrom;
10484 int32_t f = 0;
10485 int32_t c = CSet;
10486 reset_pal_cycling();
10487 // loadlvlpal(Map.CurrScr()->color);
10488 rebuild_trans_table();
10489 select_tile(t, f, 0, c, true);
10490 refresh(rALL);
10491 return D_O_K;
10492 }
10493
10494 int32_t combopage_animate = 1;
10495 void draw_combo(BITMAP *dest, int x,int y,int c,int cs,bool animate)
10496 {
10497 if(unsigned(c)<MAXCOMBOS)
10498 {
10499 newcombo& cmb = combobuf[c];
10500 int t = cmb.tile;
10501 if(!animate)
10502 cmb.tile = cmb.o_tile;
10503 put_combo(dest,x,y,c,cs,0,0);
10504 cmb.tile = t;
10505 }
10506 else
10507 {
10508 rectfill(dest,x,y,x+32-1,y+32-1,0);
10509 }
10510 }
10511
10512 void draw_combos(int32_t page,int32_t cs,bool cols)
10513 {
10514 clear_bitmap(screen2);
10515 BITMAP *buf = create_bitmap_ex(8,16,16);
10516
10517 int32_t w = 32;
10518 int32_t h = 32;
10519 int32_t mul = 2;
10520
10521 int32_t window_xofs=(zq_screen_w-640-12)>>1;
10522 int32_t window_yofs=(zq_screen_h-480-25-6)>>1;
10523 int32_t screen_xofs=window_xofs+6;
10524 int32_t screen_yofs=window_yofs+25;
10525
10526 if(cols==false)
10527 {
10528 for(int32_t i=0; i<256; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
10529 {
10530 int32_t x = (i%COMBOS_PER_ROW)*w;
10531 int32_t y = (i/COMBOS_PER_ROW)*h;
10532
10533 combotile_override_x = x+screen_xofs+(w-16)/2;
10534 combotile_override_y = y+screen_yofs+(h-16)/2;
10535 draw_combo(buf,0,0,i+(page<<8),cs,combopage_animate);
10536 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10537 }
10538 }
10539 else
10540 {
10541 int32_t c = 0;
10542
10543 for(int32_t i=0; i<256; i++)
10544 {
10545 int32_t x = (i%COMBOS_PER_ROW)*w;
10546 int32_t y = (i/COMBOS_PER_ROW)*h;
10547
10548 combotile_override_x = x+screen_xofs+(w-16)/2;
10549 combotile_override_y = y+screen_yofs+(h-16)/2;
10550 draw_combo(buf,0,0,c+(page<<8),cs,combopage_animate);
10551 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10552 ++c;
10553
10554 if((i&3)==3)
10555 c+=48;
10556
10557 if((i%COMBOS_PER_ROW)==(COMBOS_PER_ROW-1))
10558 c-=256;
10559 }
10560 }
10561 combotile_override_x = combotile_override_y = -1;
10562
10563 for(int32_t x=(64*mul); x<(320*mul); x+=(64*mul))
10564 {
10565 vline(screen2,x,0,(208*mul)-1,vc(15));
10566 }
10567
10568 destroy_bitmap(buf);
10569 }
10570
10571 void combo_info(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,int32_t buttons)
10572 {
10573 int32_t yofs=3;
10574 static BITMAP *buf = create_bitmap_ex(8,16,16);
10575 int32_t mul = 2;
10576 FONT *tfont = get_zc_font(font_lfont_l);
10577
10578 rectfill(screen2,0,210*2,(320*2)-1,(240*2)-1,jwin_pal[jcBOX]);
10579 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
10580 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
10581
10582 jwin_draw_frame(screen2,(31*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10583
10584 if(copy>=0)
10585 {
10586 put_combo(buf,0,0,copy,cs,0,0);
10587 stretch_blit(buf,screen2,0,0,16,16,31*mul,216*mul+yofs,16*mul,16*mul);
10588
10589 if(copycnt>1)
10590 {
10591 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
10592 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
10593 }
10594 else
10595 {
10596 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
10597 }
10598 }
10599 else
10600 {
10601 if (InvalidBG == 2)
10602 {
10603 draw_checkerboard(screen2, 31 * mul, 216 * mul + yofs, 16 * mul);
10604 }
10605 else if(InvalidBG == 1)
10606 {
10607 for(int32_t dy=0; dy<16*mul; dy++)
10608 {
10609 for(int32_t dx=0; dx<16*mul; dx++)
10610 {
10611 screen2->line[(216*mul)+yofs+dy][(31*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10612 }
10613 }
10614 }
10615 else
10616 {
10617 rectfill(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(0));
10618 rect(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10619 line(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10620 line(screen2, (31*mul), (216*mul)+yofs+31, (31*mul)+31, (216*mul)+yofs, vc(15));
10621 }
10622 }
10623
10624 jwin_draw_frame(screen2,(53*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10625 put_combo(buf,0,0,tile,cs,0,0);
10626 stretch_blit(buf,screen2,0,0,16,16,53*mul,216*mul+yofs,16*mul,16*mul);
10627
10628 if(tile>tile2)
10629 {
10630 zc_swap(tile,tile2);
10631 }
10632
10633 char cbuf[8];
10634 cbuf[0]=0;
10635
10636 if(tile2!=tile)
10637 {
10638 sprintf(cbuf,"-%d",tile2);
10639 }
10640
10641 textprintf_ex(screen2,tfont,(73*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"combo: CSet %d", cs);
10642 textprintf_ex(screen2,tfont,(73*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,cbuf);
10643
10644 if(tile2==tile)
10645 {
10646 int32_t nextcombo=combobuf[tile].nextcombo;
10647 int32_t nextcset=(combobuf[tile].animflags & AF_CYCLENOCSET) ? cs : combobuf[tile].nextcset;
10648 jwin_draw_frame(screen2,(136*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10649
10650 if(nextcombo>0 && !(combobuf[tile].animflags & AF_CYCLEUNDERCOMBO))
10651 {
10652 put_combo(buf,0,0,nextcombo,nextcset,0,0);
10653 stretch_blit(buf,screen2,0,0,16,16,136*mul,216*mul+yofs,16*mul,16*mul);
10654 }
10655 else
10656 {
10657 if (InvalidBG == 2)
10658 {
10659 draw_checkerboard(screen2, 136 * mul, 216 * mul + yofs, 16 * mul);
10660 }
10661 else if(InvalidBG == 1)
10662 {
10663 for(int32_t dy=0; dy<16*mul; dy++)
10664 {
10665 for(int32_t dx=0; dx<16*mul; dx++)
10666 {
10667 screen2->line[(216*mul)+yofs+dy][(136*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10668 }
10669 }
10670 }
10671 else
10672 {
10673 rectfill(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(0));
10674 rect(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10675 line(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10676 line(screen2, (136*mul), (216*mul)+yofs+31, (136*mul)+31, (216*mul)+yofs, vc(15));
10677 }
10678 }
10679
10680 textprintf_right_ex(screen2,tfont,(132*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Cycle:");
10681 textprintf_right_ex(screen2,tfont,(132*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",nextcombo);
10682 }
10683
10684
10685 FONT *tf = font;
10686 font = tfont;
10687
10688 draw_checkbox(screen2,320,440+yofs,16,combopage_animate);
10689 textprintf_ex(screen2,tfont,320+18,440+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Animate");
10690
10691 if(buttons&2)
10692 {
10693 draw_text_button(screen2,404,426+yofs,88,42,"Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10694 }
10695
10696 if(buttons&4)
10697 {
10698 draw_text_button(screen2,494,426+yofs,88,42,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10699 }
10700
10701 font = tf;
10702
10703 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
10704 textprintf_ex(screen2,tfont,(293*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
10705 textprintf_centre_ex(screen2,tfont,(309*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
10706 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
10707
10708 int32_t w = 640;
10709 int32_t h = 480;
10710 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10711 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10712 int32_t screen_xofs=window_xofs+6;
10713 int32_t screen_yofs=window_yofs+25;
10714
10715 custom_vsync();
10716 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
10717 SCRFIX();
10718 //destroy_bitmap(buf);
10719 }
10720
10721 void sel_combo(int32_t &tile, int32_t &tile2, int32_t s, bool cols)
10722 {
10723 int32_t page = tile&0xFF00;
10724 tile &= 0xFF;
10725
10726 if(!cols)
10727 tile += s;
10728 else
10729 {
10730 if(s==-COMBOS_PER_ROW)
10731 tile-=4;
10732
10733 if(s==COMBOS_PER_ROW)
10734 tile+=4;
10735
10736 if(s==-1)
10737 tile-=1;
10738
10739 if(s==1)
10740 tile+=1;
10741 }
10742
10743 /*
10744 if(s==1)
10745 {
10746 if((tile&3)==3)
10747 tile+=48;
10748 else
10749 ++tile;
10750 }
10751 if(s==-1)
10752 {
10753 if((tile&3)==0)
10754 tile-=48;
10755 else
10756 --tile;
10757 }
10758 }
10759 */
10760 bound(tile,0,255);
10761 tile += page;
10762
10763 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
10764 tile2 = tile;
10765 }
10766
10767 void draw_combo_list_window()
10768 {
10769 int32_t window_xofs=0;
10770 int32_t window_yofs=0;
10771 int32_t w = 640;
10772 int32_t h = 480;
10773
10774 window_xofs=(zq_screen_w-w-12)>>1;
10775 window_yofs=(zq_screen_h-h-25-6)>>1;
10776 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
10777 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
10778 FONT *oldfont = font;
10779 font = get_zc_font(font_lfont);
10780 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Combo", true);
10781 font=oldfont;
10782 }
10783
10784
10785 static int32_t _selected_combo=-1, _selected_cset=-1;
10786 bool select_combo_2(int32_t &cmb,int32_t &cs)
10787 {
10788 popup_zqdialog_start();
10789 reset_combo_animations();
10790 reset_combo_animations2();
10791 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
10792 // static int32_t cmb=0;
10793 int32_t page=cmb>>8;
10794 int32_t tile2=cmb;
10795 int32_t done=0;
10796 int32_t tile_clicked=-1;
10797 int32_t t2;
10798 int32_t copy=-1;
10799 int32_t copycnt=0;
10800
10801 position_mouse_z(0);
10802
10803 go();
10804 int32_t w = 640;
10805 int32_t h = 480;
10806 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10807 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10808 int32_t screen_xofs=window_xofs+6;
10809 int32_t screen_yofs=window_yofs+25;
10810 int32_t panel_yofs=3;
10811 int32_t mul = 2;
10812 FONT *tfont = get_zc_font(font_lfont_l);
10813
10814 draw_combo_list_window();
10815 draw_combos(page,cs,true);
10816 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
10817
10818 while(gui_mouse_b())
10819 {
10820 /* do nothing */
10821 rest(1);
10822 }
10823
10824 bool bdown=false;
10825 int32_t f=0;
10826 int otl = cmb, otl2 = tile2;
10827
10828 do
10829 {
10830 HANDLE_CLOSE_ZQDLG();
10831 if(exiting_program) break;
10832 rest(4);
10833 bool redraw=false;
10834
10835 if(mouse_z<0)
10836 {
10837 if(page<COMBO_PAGES-1)
10838 {
10839 ++page;
10840 cmb=tile2=(page<<8)+(cmb&0xFF);
10841 }
10842
10843 position_mouse_z(0);
10844 redraw=true;
10845 }
10846 else if(mouse_z>0)
10847 {
10848 if(page>0)
10849 {
10850 --page;
10851 cmb=tile2=(page<<8)+(cmb&0xFF);
10852 }
10853
10854 position_mouse_z(0);
10855 redraw=true;
10856 }
10857
10858 if(keypressed())
10859 {
10860 switch(readkey()>>8)
10861 {
10862 case KEY_DEL:
10863 cmb=0;
10864 done=2;
10865 break;
10866
10867 case KEY_ENTER_PAD:
10868 case KEY_ENTER:
10869 done=2;
10870 break;
10871
10872 case KEY_ESC:
10873 done=1;
10874 break;
10875
10876 case KEY_F1:
10877 onHelp();
10878 break;
10879
10880 case KEY_EQUALS:
10881 case KEY_PLUS_PAD:
10882 cs = (cs<13) ? cs+1:0;
10883 redraw=true;
10884 break;
10885
10886 case KEY_MINUS:
10887 case KEY_MINUS_PAD:
10888 cs = (cs>0) ? cs-1:13;
10889 redraw=true;
10890 break;
10891
10892 case KEY_UP:
10893 sel_combo(cmb,tile2,-COMBOS_PER_ROW,true);
10894 redraw=true;
10895 break;
10896
10897 case KEY_DOWN:
10898 sel_combo(cmb,tile2,COMBOS_PER_ROW,true);
10899 redraw=true;
10900 break;
10901
10902 case KEY_LEFT:
10903 sel_combo(cmb,tile2,-1,true);
10904 redraw=true;
10905 break;
10906
10907 case KEY_RIGHT:
10908 sel_combo(cmb,tile2,1,true);
10909 redraw=true;
10910 break;
10911
10912 case KEY_PGUP:
10913 if(page>0)
10914 {
10915 --page;
10916 cmb=tile2=(page<<8)+(cmb&0xFF);
10917 }
10918
10919 redraw=true;
10920 break;
10921
10922 case KEY_PGDN:
10923 if(page<COMBO_PAGES-1)
10924 {
10925 ++page;
10926 cmb=tile2=(page<<8)+(cmb&0xFF);
10927 }
10928
10929 redraw=true;
10930 break;
10931
10932 case KEY_P:
10933 {
10934 int32_t choosepage=getnumber("Goto Page", (PreFillComboEditorPage?page:0));
10935
10936 if(!cancelgetnum)
10937 page=(zc_min(choosepage,COMBO_PAGES-1));
10938
10939 cmb=tile2=(page<<8)+(cmb&0xFF);
10940 redraw=true;
10941 break;
10942 }
10943 }
10944
10945 clear_keybuf();
10946 }
10947
10948 if(gui_mouse_b()&1)
10949 {
10950 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
10951 {
10952 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
10953 {
10954 done=1;
10955 }
10956 }
10957
10958 int32_t x=gui_mouse_x()-screen_xofs;
10959 int32_t y=gui_mouse_y()-screen_yofs;
10960
10961 if(y>=0 && y<208*mul)
10962 {
10963 x=zc_min(zc_max(x,0),(320*mul)-1);
10964 int32_t t;
10965
10966 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10967
10968 bound(t,0,255);
10969 t+=page<<8;
10970 cmb=tile2=t;
10971
10972 if(tile_clicked!=t)
10973 {
10974 dclick_status=DCLICK_NOT;
10975 }
10976 else if(dclick_status == DCLICK_AGAIN)
10977 {
10978 while(gui_mouse_b())
10979 {
10980 /* do nothing */
10981 }
10982
10983 t2 = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10984
10985 if(t2!=t)
10986 {
10987 dclick_status=DCLICK_NOT;
10988 }
10989 else
10990 {
10991 done=2;
10992 }
10993 }
10994
10995 tile_clicked=t;
10996 }
10997 else if(y>=(208*mul) && x>(300*mul) && !bdown)
10998 {
10999 if(y<(224*mul)+panel_yofs && page>0)
11000 {
11001 --page;
11002 redraw=true;
11003 }
11004
11005 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
11006 {
11007 ++page;
11008 redraw=true;
11009 }
11010
11011 bdown=true;
11012 }
11013
11014 if(!bdown && isinRect(x,y,(247*mul),(213*mul),((247+44)*mul),((213+21)*mul)))
11015 {
11016 FONT *tf = font;
11017 font = tfont;
11018
11019 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
11020 {
11021 done=2;
11022 }
11023
11024 font = tf;
11025 }
11026 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
11027 {
11028 FONT *tf = font;
11029 font = tfont;
11030
11031 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
11032 combopage_animate = combopage_animate ? 0 : 1;
11033 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
11034 redraw = true;
11035
11036 font = tf;
11037 }
11038
11039 bdown=true;
11040 }
11041
11042 bool r_click = false;
11043
11044 if(gui_mouse_b()&2 && !bdown)
11045 {
11046 int32_t x=gui_mouse_x()+screen_xofs;
11047 int32_t y=gui_mouse_y()+screen_yofs;
11048
11049 if(y>=0 && y<208*mul)
11050 {
11051 x=zc_min(zc_max(x,0),(320*mul)-1);
11052 int32_t t;
11053
11054 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11055
11056 bound(t,0,255);
11057 t+=page<<8;
11058
11059 if(t<zc_min(cmb,tile2) || t>zc_max(cmb,tile2))
11060 cmb=tile2=t;
11061 }
11062
11063 bdown = r_click = true;
11064 f=8;
11065 }
11066
11067 if(gui_mouse_b()==0)
11068 bdown=false;
11069
11070 if((f%8) || InvalidBG == 1)
11071 redraw = true;
11072 if(otl != cmb || otl2 != tile2)
11073 {
11074 otl = cmb;
11075 otl2 = tile2;
11076 redraw = true;
11077 }
11078
11079 if(redraw || combopage_animate)
11080 draw_combos(page,cs,true);
11081
11082 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
11083
11084 if(f&8)
11085 {
11086 int32_t x,y;
11087
11088 for(int32_t i=zc_min(cmb,tile2); i<=zc_max(cmb,tile2); i++)
11089 {
11090 if((i>>8)==page)
11091 {
11092 int32_t t=i&255;
11093
11094 x=((t&3) + ((t/52)<<2)) << 5;
11095 y=((t%52)>>2) << 5;
11096
11097 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11098 }
11099 }
11100
11101 SCRFIX();
11102 }
11103
11104 ++f;
11105
11106 }
11107 while(!done);
11108
11109 while(gui_mouse_b())
11110 {
11111 /* do nothing */
11112 rest(1);
11113 }
11114
11115 comeback();
11116 setup_combo_animations();
11117 setup_combo_animations2();
11118
11119 bool ret = done==2;
11120 if(ret)
11121 {
11122 _selected_combo = cmb;
11123 _selected_cset = cs;
11124 }
11125
11126 popup_zqdialog_end();
11127 return ret;
11128 }
11129
11130 bool select_combo_3(int32_t &cmb,int32_t &cs)
11131 {
11132 if(_selected_combo < 0)
11133 {
11134 _selected_combo = Combo;
11135 _selected_cset = CSet;
11136 }
11137 cmb = _selected_combo;
11138 cs = _selected_cset;
11139 return select_combo_2(cmb,cs);
11140 }
11141
11142 bool advpaste(int32_t tile, int32_t tile2, int32_t copy)
11143 {
11144 static bitstring pasteflags;
11145 static const vector<CheckListInfo> advp_names =
11146 {
11147 { "Tile" },
11148 { "CSet2" },
11149 { "Solidity" },
11150 { "Animation" },
11151 { "Type" },
11152 { "Inherent Flag" },
11153 { "Attributes", "Including Attribytes and Attrishorts" },
11154 { "Flags", "The 16 Flags on the 'Flags' tab" },
11155 { "Gen. Flags", "The 2 'General Flags' on the 'Flags' tab" },
11156 { "Label" },
11157 { "Script" },
11158 { "Effect" },
11159 { "Triggers Tab" },
11160 { "Lifting Tab" },
11161 { "Gen: Movespeed", "The Movespeed related values from the 'General' tab" },
11162 { "Gen: SFX", "The SFX related values from the 'General' tab" },
11163 { "Gen: Sprites", "The Sprites related values from the 'General' tab" },
11164 { "Gen: Z Height", "The combo's 'Z Height'/'Z Step Height' settings, and related flags" },
11165 { "Misc Weapon Data", "The combo's 'Misc Weapon Data' settings" },
11166 // should be CMB_ADVP_SZ long
11167 };
11168
11169 if(!call_checklist_dialog("Advanced Paste",advp_names,pasteflags))
11170 return false;
11171
11172 //Paste to each combo in the range
11173 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11174 combobuf[i].advpaste(combobuf[copy], pasteflags);
11175
11176 if(pasteflags.get(CMB_ADVP_TILE)) //reset animations if needed
11177 {
11178 setup_combo_animations();
11179 setup_combo_animations2();
11180 }
11181
11182 return true;
11183 }
11184
11185 int32_t combo_screen(int32_t pg, int32_t tl)
11186 {
11187 popup_zqdialog_start();
11188 reset_combo_animations();
11189 reset_combo_animations2();
11190 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
11191 static int32_t tile=0;
11192 static int32_t page=0;
11193
11194 if(pg>-1)
11195 page = pg;
11196
11197 if(tl>-1)
11198 tile = tl;
11199
11200 int32_t tile2=tile;
11201 int32_t done=0;
11202 int32_t cs = CSet;
11203 int32_t copy=-1;
11204 int32_t copycnt=0;
11205
11206 int32_t tile_clicked=-1;
11207 int32_t t2;
11208
11209 bool masscopy;
11210
11211 go();
11212 int32_t w = 640;
11213 int32_t h = 480;
11214 int32_t window_xofs=(zq_screen_w-w-12)>>1;
11215 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
11216 int32_t screen_xofs=window_xofs+6;
11217 int32_t screen_yofs=window_yofs+25;
11218 int32_t panel_yofs=3;
11219 int32_t mul = 2;
11220 FONT *tfont = get_zc_font(font_lfont_l);
11221
11222 draw_combo_list_window();
11223 draw_combos(page,cs,true);
11224 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11225 go_combos();
11226 position_mouse_z(0);
11227
11228 while(gui_mouse_b())
11229 {
11230 /* do nothing */
11231 }
11232
11233 bool bdown=false;
11234 int32_t f=0;
11235 int otl = tile, otl2 = tile2;
11236
11237 do
11238 {
11239 HANDLE_CLOSE_ZQDLG();
11240 if(exiting_program) break;
11241 rest(4);
11242 bool redraw=false;
11243
11244 if(mouse_z<0)
11245 {
11246 if(page<COMBO_PAGES-1)
11247 {
11248 ++page;
11249 tile=tile2=(page<<8)+(tile&0xFF);
11250 }
11251
11252 position_mouse_z(0);
11253 redraw=true;
11254 }
11255 else if(mouse_z>0)
11256 {
11257 if(page>0)
11258 {
11259 --page;
11260 tile=tile2=(page<<8)+(tile&0xFF);
11261 }
11262
11263 position_mouse_z(0);
11264 redraw=true;
11265 }
11266
11267 if(keypressed())
11268 {
11269 switch(readkey()>>8)
11270 {
11271 case KEY_ENTER_PAD:
11272 case KEY_ENTER:
11273 done=2;
11274 break;
11275
11276 case KEY_ESC:
11277 done=1;
11278 break;
11279
11280 case KEY_F1:
11281 onHelp();
11282 break;
11283
11284 case KEY_EQUALS:
11285 case KEY_PLUS_PAD:
11286 if(CHECK_CTRL_CMD)
11287 {
11288 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11289 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11290 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11291
11292 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11293 {
11294 combobuf[i].set_tile(wrap(combobuf[i].o_tile + amnt,
11295 0, NEWMAXTILES-1));
11296 }
11297
11298 setup_combo_animations();
11299 redraw=true;
11300 }
11301 else
11302 {
11303 cs = (cs<13) ? cs+1:0;
11304 redraw=true;
11305 }
11306
11307 break;
11308
11309 case KEY_MINUS:
11310 case KEY_MINUS_PAD:
11311 if(CHECK_CTRL_CMD)
11312 {
11313 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11314 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11315 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11316
11317 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11318 {
11319 combobuf[i].set_tile(wrap(combobuf[i].o_tile - amnt,
11320 0, NEWMAXTILES-1));
11321 }
11322
11323 setup_combo_animations();
11324 redraw=true;
11325 }
11326 else
11327 {
11328 cs = (cs>0) ? cs-1:13;
11329 redraw=true;
11330 }
11331
11332 break;
11333
11334 case KEY_UP:
11335 sel_combo(tile,tile2,-COMBOS_PER_ROW,true);
11336 redraw=true;
11337 break;
11338
11339 case KEY_DOWN:
11340 sel_combo(tile,tile2,COMBOS_PER_ROW,true);
11341 redraw=true;
11342 break;
11343
11344 case KEY_LEFT:
11345 sel_combo(tile,tile2,-1,true);
11346 redraw=true;
11347 break;
11348
11349 case KEY_RIGHT:
11350 sel_combo(tile,tile2,1,true);
11351 redraw=true;
11352 break;
11353
11354 case KEY_PGUP:
11355 if(page>0)
11356 {
11357 --page;
11358 tile=tile2=(page<<8)+(tile&0xFF);
11359 }
11360
11361 redraw=true;
11362 break;
11363
11364 case KEY_PGDN:
11365 if(page<COMBO_PAGES-1)
11366 {
11367 ++page;
11368 tile=tile2=(page<<8)+(tile&0xFF);
11369 }
11370
11371 redraw=true;
11372 break;
11373
11374 case KEY_A:
11375 {
11376 tile=(page<<8);
11377 tile2=(page<<8)+(0xFF);
11378 }
11379
11380 redraw=true;
11381 break;
11382
11383 case KEY_P:
11384 {
11385 int32_t choosepage = getnumber("Goto Page", (PreFillComboEditorPage?page:0));
11386
11387 if(!cancelgetnum)
11388 page=(zc_min(choosepage,COMBO_PAGES-1));
11389
11390 tile=tile2=(page<<8)+(tile&0xFF);
11391 redraw=true;
11392 }
11393 break;
11394
11395 case KEY_U:
11396 comeback_combos();
11397 redraw=true;
11398 break;
11399
11400 case KEY_E:
11401 go_combos();
11402 edit_combo(tile,false,cs);
11403 redraw=true;
11404 setup_combo_animations();
11405 setup_combo_animations2();
11406 break;
11407
11408 case KEY_C:
11409 go_combos();
11410 copy=zc_min(tile,tile2);
11411 copycnt=abs(tile-tile2)+1;
11412 redraw=true;
11413 break;
11414
11415 case KEY_H:
11416 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11417 {
11418 combobuf[i].flip^=1;
11419 byte w2=combobuf[i].walk;
11420 combobuf[i].walk=((w2& ~0x33)>>2 | (w2&0x33)<<2);
11421 w2=combobuf[i].csets;
11422 combobuf[i].csets= (((w2& ~0x50)>>1 | (w2&0x50)<<1) & ~0x0F) | (w2 & 0x0F);
11423 }
11424
11425 redraw=true;
11426 saved=false;
11427 break;
11428
11429 case KEY_M:
11430 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
11431 {
11432 move_combos(tile,tile2,copy,copycnt);
11433 saved=false;
11434 }
11435
11436 redraw=true;
11437 break;
11438
11439 case KEY_S:
11440 tile=tile2=zc_min(tile,tile2);
11441
11442 if(copy>=0 && tile!=copy)
11443 {
11444 go_combos();
11445
11446 for(int32_t i=0; i<copycnt; i++)
11447 {
11448 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11449 }
11450
11451 saved=false;
11452 setup_combo_animations();
11453 setup_combo_animations2();
11454 }
11455
11456 redraw=true;
11457 copy=-1;
11458 break;
11459
11460 case KEY_V:
11461 if((CHECK_CTRL_CMD) && copy != -1)
11462 {
11463 if(advpaste(tile, tile2, copy))
11464 {
11465 saved=false;
11466 redraw=true;
11467 copy=-1;
11468 }
11469
11470 break;
11471 }
11472
11473 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11474
11475 if(copy==-1)
11476 {
11477 go_combos();
11478
11479 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11480 {
11481 combobuf[i].flip^=2;
11482 byte w2=combobuf[i].walk;
11483 combobuf[i].walk=(w2&0x55)<<1 | (w2& ~0x55)>>1;
11484 w2=combobuf[i].csets;
11485 combobuf[i].csets= (((w2&0x30)<<2 | (w2& ~0x30)>>2) & ~0x0F) | (w2 & 0x0F);
11486 }
11487
11488 saved=false;
11489 }
11490 else
11491 {
11492 go_combos();
11493 copy_combos(tile,tile2,copy,copycnt,masscopy);
11494 setup_combo_animations();
11495 setup_combo_animations2();
11496 saved=false;
11497 }
11498
11499 redraw=true;
11500 break;
11501 case KEY_R:
11502 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11503 {
11504 combobuf[i].flip = rotate_value(combobuf[i].flip);
11505 combobuf[i].walk = rotate_walk(combobuf[i].walk);
11506 combobuf[i].csets = rotate_cset(combobuf[i].csets);
11507 }
11508
11509 redraw=true;
11510 saved=false;
11511 break;
11512
11513 case KEY_I:
11514 {
11515 // rev.1509; Can now insert/remove all selected combos
11516 int32_t z=tile;
11517 int32_t numSelected = abs(tile-tile2) + 1;
11518 tile=zc_min(tile,tile2);
11519 tile2=MAXCOMBOS;
11520 copy = tile + numSelected; // copy=tile+1;
11521 copycnt = MAXCOMBOS-tile-numSelected; // copycnt=MAXCOMBOS-tile;
11522
11523 if(key[KEY_LSHIFT]||key[KEY_RSHIFT])
11524 {
11525 char buf[64];
11526
11527 if(numSelected>1)
11528 sprintf(buf,"Remove combos %d - %d?",tile, copy-1);
11529 else
11530 sprintf(buf,"Remove combo %d?",tile);
11531
11532 if(jwin_alert("Confirm Remove",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11533 {
11534 move_combos(tile,tile2,copy, copycnt);
11535 //don't allow the user to undo; quest combo references are incorrect -DD
11536 go_combos();
11537 redraw=true;
11538 saved=false;
11539 }
11540 }
11541 else
11542 {
11543 char buf[64];
11544
11545 if(numSelected>1)
11546 sprintf(buf,"Insert %d blank combos?",numSelected);
11547 else
11548 sprintf(buf,"Insert a blank combo?");
11549
11550 if(jwin_alert("Confirm Insert",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11551 {
11552 move_combos(copy,tile2,tile, copycnt);
11553 go_combos();
11554 redraw=true;
11555 saved=false;
11556 }
11557 }
11558
11559 copy=-1;
11560 tile2=tile=z;
11561 }
11562 break;
11563
11564 case KEY_DEL:
11565 {
11566 char buf[40];
11567
11568 if(tile==tile2)
11569 {
11570 sprintf(buf,"Delete combo %d?",tile);
11571 }
11572 else
11573 {
11574 sprintf(buf,"Delete combos %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
11575 }
11576
11577 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11578 {
11579 go_combos();
11580
11581 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11582 {
11583 clear_combo(i);
11584 }
11585
11586 tile=tile2=zc_min(tile,tile2);
11587 redraw=true;
11588 saved=false;
11589 setup_combo_animations();
11590 setup_combo_animations2();
11591 }
11592 }
11593 break;
11594 }
11595
11596 clear_keybuf();
11597 }
11598
11599 if(gui_mouse_b()&1)
11600 {
11601 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
11602 {
11603 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
11604 {
11605 done=1;
11606 }
11607 }
11608
11609 int32_t x=gui_mouse_x()-screen_xofs;
11610 int32_t y=gui_mouse_y()-screen_yofs;
11611
11612 if(y>=0 && y<(208*mul))
11613 {
11614 x=zc_min(zc_max(x,0),(320*mul)-1);
11615 int32_t t;
11616
11617 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11618
11619 bound(t,0,255);
11620 t+=page<<8;
11621
11622 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
11623 {
11624 tile2=t;
11625 }
11626 else
11627 {
11628 tile=tile2=t;
11629 }
11630
11631 if(tile_clicked!=t)
11632 {
11633 dclick_status=DCLICK_NOT;
11634 }
11635 else if(dclick_status == DCLICK_AGAIN)
11636 {
11637 while(gui_mouse_b())
11638 {
11639 /* do nothing */
11640 rest(1);
11641 }
11642
11643 t2 = ((x>>6)*52) + ((x>>4)&3) + ((y>>4)<<2);
11644
11645 bound(t2,0,255);
11646 t2+=page<<8;
11647
11648 if(t2!=t)
11649 {
11650 dclick_status=DCLICK_NOT;
11651 }
11652 else
11653 {
11654 go_combos();
11655 edit_combo(tile,false,cs);
11656 redraw=true;
11657 setup_combo_animations();
11658 setup_combo_animations2();
11659 }
11660 }
11661
11662 tile_clicked=t;
11663 }
11664 else if(x>(300*mul) && !bdown)
11665 {
11666 if(y<(224*mul)+panel_yofs && page>0)
11667 {
11668 --page;
11669 redraw=true;
11670 }
11671
11672 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
11673 {
11674 ++page;
11675 redraw=true;
11676 }
11677
11678 bdown=true;
11679 }
11680
11681 if(!bdown && isinRect(x,y,(202*mul),(213*mul)+panel_yofs,(202+44)*mul,(213+21)*mul))
11682 {
11683 FONT *tf = font;
11684 font = tfont;
11685
11686 if(do_text_button((202*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Edit"))
11687 {
11688 font = tf;
11689 edit_combo(tile,false,cs);
11690 redraw=true;
11691 }
11692
11693 font = tf;
11694 }
11695 else if(!bdown && isinRect(x,y,(247*mul),(213*mul)+panel_yofs,(247+44)*mul,(213+21)*mul))
11696 {
11697 FONT *tf = font;
11698 font = tfont;
11699
11700 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
11701 {
11702 done=1;
11703 }
11704
11705 font = tf;
11706 }
11707 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
11708 {
11709 FONT *tf = font;
11710 font = tfont;
11711
11712 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
11713 combopage_animate = combopage_animate ? 0 : 1;
11714 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
11715 redraw = true;
11716
11717 font = tf;
11718 }
11719
11720 bdown=true;
11721 }
11722
11723 bool r_click = false;
11724
11725 if(gui_mouse_b()&2 && !bdown)
11726 {
11727 int32_t x=gui_mouse_x()-screen_xofs;
11728 int32_t y=gui_mouse_y()-screen_yofs;
11729
11730 if(y>=0 && y<(208*mul))
11731 {
11732 x=zc_min(zc_max(x,0),(320*mul)-1);
11733 int32_t t;
11734
11735 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11736
11737 bound(t,0,255);
11738 t+=page<<8;
11739
11740 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
11741 {
11742 tile=tile2=t;
11743 }
11744 }
11745
11746 bdown = r_click = true;
11747 f=8;
11748 }
11749
11750 REDRAW:
11751
11752 if(gui_mouse_b()==0)
11753 bdown=false;
11754
11755 if((f%8) || InvalidBG == 1)
11756 redraw = true;
11757 if(otl != tile || otl2 != tile2)
11758 {
11759 otl = tile;
11760 otl2 = tile2;
11761 redraw = true;
11762 }
11763
11764 if(redraw || combopage_animate)
11765 draw_combos(page,cs,true);
11766
11767 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11768
11769 if(f&8)
11770 {
11771 int32_t x,y;
11772
11773 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11774 {
11775 if((i>>8)==page)
11776 {
11777 int32_t t=i&255;
11778
11779 x=((t&3) + ((t/52)<<2)) << 5;
11780 y=((t%52)>>2) << 5;
11781
11782 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11783 }
11784 }
11785
11786 SCRFIX();
11787 }
11788
11789 ++f;
11790
11791 //Seriously? There is duplicate code for the r-click menu? -Gleeok
11792 if(r_click)
11793 {
11794 NewMenu rcmenu
11795 {
11796 { "Copy", [&]()
11797 {
11798 go_combos();
11799 copy=zc_min(tile,tile2);
11800 copycnt=abs(tile-tile2)+1;
11801 } },
11802 { "Paste", [&]()
11803 {
11804 if((CHECK_CTRL_CMD))
11805 {
11806 if(advpaste(tile, tile2, copy))
11807 {
11808 saved=false;
11809 redraw=true;
11810 copy=-1;
11811 }
11812 return;
11813 }
11814
11815 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11816
11817 go_combos();
11818 copy_combos(tile,tile2,copy,copycnt,masscopy);
11819 setup_combo_animations();
11820 setup_combo_animations2();
11821 saved=false;
11822 }, nullopt, copy < 0 ? MFL_DIS : 0 },
11823 { "Adv. Paste", [&]()
11824 {
11825 if(advpaste(tile, tile2, copy))
11826 {
11827 saved=false;
11828 redraw=true;
11829 copy=-1;
11830 }
11831 }, nullopt, copy < 0 ? MFL_DIS : 0 },
11832 { "Move", [&]()
11833 {
11834 if(copy!=zc_min(tile,tile2))
11835 {
11836 move_combos(tile,tile2,copy,copycnt);
11837 saved=false;
11838 setup_combo_animations();
11839 setup_combo_animations2();
11840 }
11841 redraw=true;
11842 }, nullopt, copy < 0 ? MFL_DIS : 0 },
11843 { "Swap", [&]()
11844 {
11845 tile=tile2=zc_min(tile,tile2);
11846
11847 if(tile!=copy)
11848 {
11849 go_combos();
11850
11851 for(int32_t i=0; i<copycnt; i++)
11852 {
11853 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11854 }
11855
11856 saved=false;
11857 setup_combo_animations();
11858 setup_combo_animations2();
11859 }
11860 copy=-1;
11861 }, nullopt, copy < 0 ? MFL_DIS : 0 },
11862 { "Delete", [&]()
11863 {
11864 string msg;
11865
11866 if(tile==tile2)
11867 msg = fmt::format("Delete combo {}?",tile);
11868 else
11869 msg = fmt::format("Delete combos {}-{}?",zc_min(tile,tile2),zc_max(tile,tile2));
11870 bool didconfirm = false;
11871 AlertDialog("Confirm Delete",msg,
11872 [&](bool ret,bool)
11873 {
11874 if(ret)
11875 didconfirm = true;
11876 }).show();
11877 if(didconfirm)
11878 {
11879 go_combos();
11880
11881 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11882 clear_combo(i);
11883
11884 tile=tile2=zc_min(tile,tile2);
11885 saved=false;
11886 }
11887 } },
11888 {},
11889 { "Edit", [&]()
11890 {
11891 go_combos();
11892 edit_combo(tile,false,cs);
11893 } },
11894 { "Insert", [&]()
11895 {
11896 int z = tile;
11897 int count = abs(tile-tile2)+1;
11898 tile = zc_min(tile,tile2);
11899 tile2 = MAXCOMBOS;
11900 copy = tile+count;
11901 copycnt = MAXCOMBOS-tile-count;
11902
11903 string msg;
11904
11905 if(count>1)
11906 msg = fmt::format("Insert combos {} - {}?"
11907 " This will offset all of the combos that follow!",tile, copy-1);
11908 else
11909 msg = fmt::format("Insert combo {}?"
11910 " This will offset all of the combos that follow!",tile);
11911
11912 bool didconfirm = false;
11913 AlertDialog("Confirm Insert",msg,
11914 [&](bool ret,bool)
11915 {
11916 if(ret)
11917 didconfirm = true;
11918 }).show();
11919 if(didconfirm)
11920 move_combos(copy, tile2, tile, copycnt);
11921 else return;
11922
11923 copy = -1;
11924 tile2 = tile = z;
11925
11926 //don't allow the user to undo; quest combo references are incorrect -DD
11927 go_combos();
11928 saved = false;
11929 } },
11930 { "Remove", [&]()
11931 {
11932 int z = tile;
11933 int count = abs(tile-tile2)+1;
11934 tile = zc_min(tile,tile2);
11935 tile2 = MAXCOMBOS;
11936 copy = tile+count;
11937 copycnt = MAXCOMBOS-tile-count;
11938
11939 string msg;
11940
11941 if(count>1)
11942 msg = fmt::format("Remove combos {} - {}?"
11943 " This will offset all of the combos that follow!",tile, copy-1);
11944 else
11945 msg = fmt::format("Remove combo {}?"
11946 " This will offset all of the combos that follow!",tile);
11947
11948 bool didconfirm = false;
11949 AlertDialog("Confirm Remove",msg,
11950 [&](bool ret,bool)
11951 {
11952 if(ret)
11953 didconfirm = true;
11954 }).show();
11955 if(didconfirm)
11956 move_combos(tile, tile2, copy, copycnt);
11957 else return;
11958
11959 copy = -1;
11960 tile2 = tile = z;
11961
11962 //don't allow the user to undo; quest combo references are incorrect -DD
11963 go_combos();
11964 saved = false;
11965 } },
11966 {},
11967 { "Locations", [&]()
11968 {
11969 int32_t z = Combo;
11970 Combo = tile;
11971 onComboLocationReport();
11972 Combo = z;
11973 } },
11974 };
11975 rcmenu.pop(window_mouse_x(),window_mouse_y());
11976 redraw = true;
11977 r_click = false;
11978 goto REDRAW;
11979 }
11980
11981 }
11982 while(!done);
11983
11984 while(gui_mouse_b())
11985 rest(1);
11986 comeback();
11987 setup_combo_animations();
11988 setup_combo_animations2();
11989 _selected_combo = tile;
11990 _selected_cset = cs;
11991 popup_zqdialog_end();
11992 return done-1;
11993 }
11994
11995 int32_t onCombos()
11996 {
11997 combo_screen(-1,-1);
11998 refresh(rALL);
11999 return D_O_K;
12000 }
12001
12002 int32_t d_ctile_proc(int32_t msg,DIALOG *d,int32_t c)
12003 {
12004 //these are here to bypass compiler warnings about unused arguments
12005 d=d;
12006 c=c;
12007
12008 if(msg==MSG_CLICK)
12009 {
12010 int32_t t=curr_combo.o_tile;
12011 int32_t f=curr_combo.flip;
12012
12013 if(select_tile(t,f,1,CSet,true,0,true))
12014 {
12015 curr_combo.tile=t;
12016 curr_combo.o_tile=t;
12017 curr_combo.flip=f;
12018 return D_REDRAW;
12019 }
12020 }
12021
12022 return D_O_K;
12023 }
12024
12025 int32_t d_combo_loader(int32_t msg,DIALOG *d,int32_t c)
12026 {
12027 //these are here to bypass compiler warnings about unused arguments
12028 c=c;
12029
12030 if(msg==MSG_DRAW)
12031 {
12032 FONT *f = get_zc_font(font_lfont_l);
12033 textprintf_ex(screen,f,d->x,d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Tile:");
12034 textprintf_ex(screen,f,d->x+((1.5)*36),d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.o_tile);
12035 textprintf_ex(screen,f,d->x,d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
12036 textprintf_ex(screen,f,d->x+((1.5)*36),d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.flip);
12037 textprintf_ex(screen,f,d->x,d->y+(36),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet2:");
12038 }
12039
12040 return D_O_K;
12041 }
12042
12043 int32_t click_d_ctile_proc()
12044 {
12045 d_ctile_proc(MSG_CLICK,NULL,0);
12046 return D_REDRAW;
12047 }
12048
12049 int32_t click_d_combo_proc();
12050
12051 const char *comboscriptdroplist(int32_t index, int32_t *list_size)
12052 {
12053 if(index<0)
12054 {
12055 *list_size = bidcomboscripts_cnt;
12056 return NULL;
12057 }
12058
12059 return bidcomboscripts[index].first.c_str();
12060 }
12061 12 ListData comboscript_list(comboscriptdroplist, &font);
12062
12063 bool call_combo_editor(int32_t);
12064 bool edit_combo(int32_t c,bool freshen,int32_t cs)
12065 {
12066 FONT* ofont = font;
12067 //CSet = cs;
12068 reset_combo_animations();
12069 reset_combo_animations2();
12070 bool edited = call_combo_editor(c);
12071 font = ofont;
12072
12073 if(freshen)
12074 {
12075 refresh(rALL);
12076 }
12077
12078 setup_combo_animations();
12079 setup_combo_animations2();
12080
12081 return edited;
12082 }
12083
12084 int32_t d_itile_proc(int32_t msg,DIALOG *d,int32_t)
12085 {
12086 switch(msg)
12087 {
12088 case MSG_CLICK:
12089 {
12090 int32_t cs = d->d2;
12091 int32_t f = 0;
12092
12093 if(select_tile(d->d1,f,1,cs,true))
12094 {
12095 int32_t ok=1;
12096
12097 if(newtilebuf[d->d1].format==tf8Bit)
12098 jwin_alert("Warning",
12099 "You have selected an 8-bit tile.",
12100 "It will not be drawn correctly",
12101 "on the file select screen.",
12102 "&OK",NULL,'o',0,get_zc_font(font_lfont));
12103
12104 return D_REDRAW;
12105 }
12106 }
12107 break;
12108
12109 case MSG_DRAW:
12110 d->w = 32+4;
12111 d->h = 32+4;
12112
12113 BITMAP *buf = create_bitmap_ex(8,16,16);
12114 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12115
12116 if(buf && bigbmp)
12117 {
12118 clear_bitmap(buf);
12119 overtile16(buf,d->d1,0,0,d->fg,0);
12120 stretch_blit(buf, bigbmp, 0,0, 16, 16, 2, 2, d->w-4, d->h-4);
12121 destroy_bitmap(buf);
12122 jwin_draw_frame(bigbmp,0, 0, d->w,d->h, FR_DEEP);
12123 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12124 destroy_bitmap(bigbmp);
12125 }
12126
12127 break;
12128 }
12129
12130 return D_O_K;
12131 }
12132
12133 static DIALOG icon_dlg[] =
12134 {
12135 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
12136 { jwin_win_proc, 70, 70, 170, 104, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Game Icons", NULL, NULL },
12137 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
12138 { d_itile_proc, 108+3, 112, 20, 20, 0, 0, 0, 0, 0, 6, NULL, NULL, NULL },
12139 { d_itile_proc, 138+3, 112, 20, 20, 0, 0, 0, 0, 0, 7, NULL, NULL, NULL },
12140 { d_itile_proc, 168+3, 112, 20, 20, 0, 0, 0, 0, 0, 8, NULL, NULL, NULL },
12141 { d_itile_proc, 198+3, 112, 20, 20, 0, 0, 0, 0, 0, 9, NULL, NULL, NULL },
12142 { jwin_button_proc, 90, 145, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12143 { jwin_button_proc, 170, 145, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12144 { jwin_text_proc, 108+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "0", NULL, NULL },
12145 { jwin_text_proc, 138+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "1", NULL, NULL },
12146 { jwin_text_proc, 168+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "2", NULL, NULL },
12147 { jwin_text_proc, 198+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "3+", NULL, NULL },
12148 { jwin_text_proc, 88, 98, 12, 9, 0, 0, 0, 0, 0, 0, (void *) "Ring:", NULL, NULL },
12149 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12150 };
12151
12152 int32_t onIcons()
12153 {
12154 PALETTE pal;
12155 // pal = RAMpal;
12156 memcpy(pal,RAMpal,sizeof(RAMpal));
12157 icon_dlg[0].dp2=get_zc_font(font_lfont);
12158
12159 for(int32_t i=0; i<4; i++)
12160 {
12161 icon_dlg[i+2].d1 = QMisc.icons[i];
12162 icon_dlg[i+2].fg = i+6;
12163 load_cset(pal, i+6, pSprite(i+spICON1));
12164 }
12165
12166 zc_set_palette(pal);
12167
12168 large_dialog(icon_dlg);
12169
12170 int32_t ret = do_zqdialog(icon_dlg,7);
12171
12172 if(ret==6)
12173 {
12174 for(int32_t i=0; i<4; i++)
12175 {
12176 if(QMisc.icons[i] != icon_dlg[i+2].d1)
12177 {
12178 QMisc.icons[i] = icon_dlg[i+2].d1;
12179 saved=false;
12180 }
12181 }
12182 }
12183
12184 zc_set_palette(RAMpal);
12185 return D_O_K;
12186 }
12187
12188 // Identical to jwin_frame_proc, but is treated differently by large_dialog()
12189 int32_t d_comboframe_proc(int32_t msg, DIALOG *d, int32_t)
12190 {
12191 if(msg == MSG_DRAW)
12192 {
12193 jwin_draw_frame(screen, d->x, d->y, d->w, d->h, d->d1);
12194 }
12195
12196 return D_O_K;
12197 }
12198
12199 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t)
12200 {
12201 switch(msg)
12202 {
12203 case MSG_CLICK:
12204 {
12205 if((d->flags&D_NOCLICK))
12206 break;
12207
12208 int32_t ret = (d->flags & D_EXIT) ? D_CLOSE : D_O_K;
12209 int32_t combo2;
12210 int32_t cs;
12211
12212 if(CHECK_ALT) //place selected cmb/cs
12213 {
12214 if(gui_mouse_b()&1)
12215 {
12216 if(!CHECK_SHIFT)
12217 d->d1 = Combo;
12218 d->fg = CSet;
12219 }
12220
12221 return ret|D_REDRAW;
12222 }
12223 else if(gui_mouse_b()&2||nextcombo_fake_click==2) //clear to 0/0
12224 {
12225 d->d1=0;
12226 d->fg=0;
12227 return ret|D_REDRAW;
12228 }
12229 else if(gui_mouse_b()&1||nextcombo_fake_click==1) //popup combo picker
12230 {
12231 combo2=d->d1;
12232 cs=d->fg;
12233
12234 if((CHECK_CTRL_CMD ? select_combo_3 : select_combo_2)(combo2, cs))
12235 {
12236 d->d1=combo2;
12237 d->fg=cs;
12238 }
12239
12240 return ret|D_REDRAW;
12241 }
12242 else return ret|D_REDRAWME;
12243 }
12244 break;
12245
12246 case MSG_DRAW:
12247 {
12248 d->w = 32;
12249 d->h = 32;
12250
12251 BITMAP *buf = create_bitmap_ex(8,16,16);
12252 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12253
12254 if(buf && bigbmp)
12255 {
12256 clear_bitmap(buf);
12257
12258 if(d->d1==-1) // Display curr_combo instead of combobuf
12259 {
12260 newcombo hold = combobuf[0];
12261 combobuf[0] = curr_combo;
12262 putcombo(buf,0,0,0,d->fg);
12263 combobuf[0] = hold;
12264 }
12265 else if(d->d1)
12266 {
12267 putcombo(buf,0,0,d->d1,d->fg);
12268 }
12269
12270 stretch_blit(buf, bigbmp, 0,0, 16, 16, 0, 0, d->w, d->h);
12271 destroy_bitmap(buf);
12272 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12273 destroy_bitmap(bigbmp);
12274 }
12275 }
12276 break;
12277 }
12278 return D_O_K;
12279 }
12280
12281 // Hey, let's have a few hundred more lines of code, why not.
12282
12283 #define MR_4BIT 0
12284 #define MR_8BIT 1
12285
12286 static byte massRecolorSrc4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12287 static byte massRecolorDest4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12288 static word massRecolor8BitCSets=0; // Which CSets are affected? One bit each.
12289
12290 static byte massRecolorSrc8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12291 static byte massRecolorDest8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12292
12293 static int32_t massRecolorDraggedColor=-1;
12294 static int32_t massRecolorCSet;
12295 static bool massRecolorIgnoreBlank=true;
12296 static byte massRecolorType=MR_4BIT;
12297
12298 // Shows the sets of colors to replace from/to.
12299 // D_CSET: Colors are 0-15 within the current CSet rather than absolute.
12300 // D_SETTABLE: Colors can be dragged and dropped onto this one.
12301 #define D_CSET D_USER
12302 #define D_SETTABLE (D_USER<<1)
12303 int32_t d_mr_cset_proc(int32_t msg, DIALOG* d, int32_t)
12304 {
12305 BITMAP* bmp=screen;
12306 int32_t colorWidth=(d->w-4)/16;
12307 byte* colors=static_cast<byte*>(d->dp);
12308
12309 switch(msg)
12310 {
12311 case MSG_DRAW:
12312 {
12313 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12314
12315 int32_t baseColor=((d->flags&D_CSET)!=0) ? massRecolorCSet*16 : 0;
12316 for(int32_t c=0; c<16; c++)
12317 {
12318 rectfill(bmp,
12319 d->x+2+c*colorWidth, d->y+2,
12320 d->x+2+((c+1)*colorWidth)-1, d->y+2+d->h-5,
12321 baseColor+colors[c]);
12322 }
12323 }
12324 break;
12325
12326 case MSG_LPRESS:
12327 {
12328 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12329
12330 if(x >= 0 && x < 16) //sanity check!
12331 {
12332 massRecolorDraggedColor=colors[x];
12333 }
12334 }
12335 break;
12336
12337 case MSG_LRELEASE: // This isn't exactly right, but it'll do...
12338 if((d->flags&D_SETTABLE)!=0 && massRecolorDraggedColor>=0)
12339 {
12340 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12341 if(x >= 0 && x < 16) //sanity check!
12342 {
12343 colors[x]=massRecolorDraggedColor;
12344 d->flags|=D_DIRTY;
12345 }
12346 }
12347 massRecolorDraggedColor=-1;
12348 break;
12349 }
12350
12351 return D_O_K;
12352 }
12353
12354 // Used for the full palette in 8-bit mode.
12355 static int32_t d_mr_palette_proc(int32_t msg, DIALOG* d, int32_t)
12356 {
12357 BITMAP* bmp=screen;
12358 int colorWidth=(d->w-4)/16;
12359 d->h = 4+(colorWidth*14);
12360 int colorHeight=colorWidth;
12361
12362 switch(msg)
12363 {
12364 case MSG_DRAW:
12365 {
12366 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12367 for(int cset=0; cset<=13; cset++)
12368 {
12369 for(int color=0; color<16; color++)
12370 {
12371 rectfill(bmp,
12372 d->x+2+color*colorWidth,
12373 d->y+2+cset*colorHeight,
12374 d->x+2+((color+1)*colorWidth)-1,
12375 d->y+2+((cset+1)*colorHeight)-1,
12376 cset*16+color);
12377 }
12378 }
12379 }
12380 break;
12381
12382 case MSG_LPRESS:
12383 {
12384 int cset=(gui_mouse_y()-(d->y+2))/colorHeight;
12385 int color=(gui_mouse_x()-(d->x+2))/colorWidth;
12386 massRecolorDraggedColor=cset*16+color;
12387 }
12388 break;
12389 }
12390
12391 return D_O_K;
12392 }
12393
12394 static DIALOG recolor_4bit_dlg[] =
12395 {
12396 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12397 { jwin_win_proc, 0, 0, 216, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12398
12399 // 1
12400 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12401 { d_mr_cset_proc, 10, 42, 196, 16, 0, 0, 0, D_CSET, 0, 0, (void *)massRecolorSrc4Bit, NULL, NULL },
12402 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12403 { d_mr_cset_proc, 10, 70, 196, 16, 0, 0, 0, D_CSET|D_SETTABLE, 0, 0, (void *)massRecolorDest4Bit, NULL, NULL },
12404
12405 // 5
12406 { jwin_text_proc, 12, 96, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Apply to which CSets in 8-bit tiles?", NULL, NULL },
12407 { jwin_check_proc, 12, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "0", NULL, NULL },
12408 { jwin_check_proc, 36, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "1", NULL, NULL },
12409 { jwin_check_proc, 60, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "2", NULL, NULL },
12410 { jwin_check_proc, 84, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "3", NULL, NULL },
12411 { jwin_check_proc, 108, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "4", NULL, NULL },
12412 { jwin_check_proc, 132, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "5", NULL, NULL },
12413 { jwin_check_proc, 156, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "6", NULL, NULL },
12414 { jwin_check_proc, 12, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "7", NULL, NULL },
12415 { jwin_check_proc, 36, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "8", NULL, NULL },
12416 { jwin_check_proc, 60, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "9", NULL, NULL },
12417 { jwin_check_proc, 84, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "10", NULL, NULL },
12418 { jwin_check_proc, 108, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "11", NULL, NULL },
12419 { jwin_check_proc, 132, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "12", NULL, NULL },
12420 { jwin_check_proc, 156, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "13", NULL, NULL },
12421
12422 // 20
12423 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12424 { jwin_func_button_proc, 14, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset4Bit },
12425 { jwin_button_proc, 82, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 8-bit mode", NULL, NULL },
12426 { jwin_button_proc, 44, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12427 { jwin_button_proc, 112, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12428
12429 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12430 };
12431
12432 #define MR4_SRC_COLORS 2
12433 #define MR4_DEST_COLORS 4
12434 #define MR4_8BIT_EFFECT_START 6
12435 #define MR4_IGNORE_BLANK 20
12436 #define MR4_RESET 21
12437 #define MR4_SWITCH 22
12438 #define MR4_OK 23
12439 #define MR4_CANCEL 24
12440
12441 static DIALOG recolor_8bit_dlg[] =
12442 {
12443 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12444 { jwin_win_proc, 0, 0, 288, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12445
12446 // 1
12447 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12448 { d_mr_cset_proc, 10, 42, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorSrc8Bit, NULL, NULL },
12449 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12450 { d_mr_cset_proc, 10, 70, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorDest8Bit, NULL, NULL },
12451 { d_mr_palette_proc, 144, 32, 132, 150, vc(15), vc(1), 0, 0, 0, 0, (void *) NULL, NULL, NULL },
12452
12453 // 6
12454 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12455 { jwin_func_button_proc, 50, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset8Bit },
12456 { jwin_button_proc, 118, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 4-bit mode", NULL, NULL },
12457 { jwin_button_proc, 80, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12458 { jwin_button_proc, 148, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12459
12460 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12461 };
12462
12463 #define MR8_SRC_COLORS 2
12464 #define MR8_DEST_COLORS 4
12465 #define MR8_PALETTE 5
12466 #define MR8_IGNORE_BLANK 6
12467 #define MR8_RESET 7
12468 #define MR8_SWITCH 8
12469 #define MR8_OK 9
12470 #define MR8_CANCEL 10
12471
12472 static void massRecolorInit(int32_t cset)
12473 {
12474 massRecolorDraggedColor=-1;
12475 massRecolorCSet=cset;
12476
12477 recolor_4bit_dlg[0].dp2=get_zc_font(font_lfont);
12478 recolor_8bit_dlg[0].dp2=get_zc_font(font_lfont);
12479
12480 for(int32_t i=0; i<=13; i++)
12481 {
12482 if((massRecolor8BitCSets&(1<<i))!=0)
12483 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags|=D_SELECTED;
12484 else
12485 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&=~D_SELECTED;
12486 }
12487
12488 if(massRecolorIgnoreBlank)
12489 {
12490 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags|=D_SELECTED;
12491 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags|=D_SELECTED;
12492 }
12493 else
12494 {
12495 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&=~D_SELECTED;
12496 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&=~D_SELECTED;
12497 }
12498
12499 large_dialog(recolor_4bit_dlg);
12500 large_dialog(recolor_8bit_dlg);
12501
12502 // Quick fix for large_dialog() screwing these up. It's ugly. Whatever.
12503 if((recolor_4bit_dlg[MR4_DEST_COLORS].w-4)%4!=0)
12504 {
12505 recolor_4bit_dlg[MR4_SRC_COLORS].x++;
12506 recolor_4bit_dlg[MR4_SRC_COLORS].w-=2;
12507 recolor_4bit_dlg[MR4_DEST_COLORS].x++;
12508 recolor_4bit_dlg[MR4_DEST_COLORS].w-=2;
12509
12510 recolor_8bit_dlg[MR8_SRC_COLORS].x++;
12511 recolor_8bit_dlg[MR8_SRC_COLORS].w-=2;
12512 recolor_8bit_dlg[MR8_DEST_COLORS].x++;
12513 recolor_8bit_dlg[MR8_DEST_COLORS].w-=2;
12514 recolor_8bit_dlg[MR8_PALETTE].x++;
12515 recolor_8bit_dlg[MR8_PALETTE].w-=2;
12516 recolor_8bit_dlg[MR8_PALETTE].y++;
12517 recolor_8bit_dlg[MR8_PALETTE].h-=2;
12518 }
12519 }
12520
12521 static void massRecolorApplyChanges()
12522 {
12523 massRecolor8BitCSets=0;
12524 for(int32_t i=0; i<=13; i++)
12525 {
12526 if((recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&D_SELECTED)!=0)
12527 massRecolor8BitCSets|=1<<i;
12528 }
12529
12530 if(massRecolorType==MR_4BIT)
12531 massRecolorIgnoreBlank=(recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&D_SELECTED)!=0;
12532 else
12533 massRecolorIgnoreBlank=(recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&D_SELECTED)!=0;
12534 }
12535
12536 static bool massRecolorSetup(int32_t cset)
12537 {
12538 massRecolorInit(cset);
12539
12540 // Remember the current colors in case the user cancels.
12541 int32_t oldDest4Bit[16], oldSrc8Bit[16], oldDest8Bit[16];
12542 for(int32_t i=0; i<16; i++)
12543 {
12544 oldDest4Bit[i]=massRecolorDest4Bit[i];
12545 oldSrc8Bit[i]=massRecolorSrc8Bit[i];
12546 oldDest8Bit[i]=massRecolorDest8Bit[i];
12547 }
12548
12549 byte type=massRecolorType;
12550 int32_t ret;
12551 do
12552 {
12553 HANDLE_CLOSE_ZQDLG();
12554 if(exiting_program) break;
12555 if(type==MR_4BIT)
12556 {
12557 ret=do_zqdialog(recolor_4bit_dlg, MR4_OK);
12558 if(ret==MR4_SWITCH)
12559 type=MR_8BIT;
12560 }
12561 else
12562 {
12563 ret=do_zqdialog(recolor_8bit_dlg, MR8_OK);
12564 if(ret==MR8_SWITCH)
12565 type=MR_4BIT;
12566 }
12567 } while(ret==MR4_SWITCH || ret==MR8_SWITCH);
12568
12569 if(ret!=MR4_OK && ret!=MR8_OK) // Canceled
12570 {
12571 for(int32_t i=0; i<16; i++)
12572 {
12573 massRecolorDest4Bit[i]=oldDest4Bit[i];
12574 massRecolorSrc8Bit[i]=oldSrc8Bit[i];
12575 massRecolorDest8Bit[i]=oldDest8Bit[i];
12576 }
12577 return false;
12578 }
12579
12580 // OK
12581 massRecolorType=type;
12582 massRecolorApplyChanges();
12583 return true;
12584 }
12585
12586 static void massRecolorApply4Bit(int32_t tile)
12587 {
12588 byte buf[256];
12589 unpack_tile(newtilebuf, tile, 0, true);
12590
12591 if(newtilebuf[tile].format==tf4Bit)
12592 {
12593 for(int32_t i=0; i<256; i++)
12594 buf[i]=massRecolorDest4Bit[unpackbuf[i]];
12595 }
12596 else // 8-bit
12597 {
12598 for(int32_t i=0; i<256; i++)
12599 {
12600 word cset=unpackbuf[i]>>4;
12601 if((massRecolor8BitCSets&(1<<cset))!=0) // Recolor this CSet?
12602 {
12603 word color=unpackbuf[i]&15;
12604 buf[i]=(cset<<4)|massRecolorDest4Bit[color];
12605 }
12606 else
12607 buf[i]=unpackbuf[i];
12608 }
12609 }
12610
12611 pack_tile(newtilebuf, buf, tile);
12612 }
12613
12614 static void massRecolorApply8Bit(int32_t tile)
12615 {
12616 byte buf[256];
12617 unpack_tile(newtilebuf, tile, 0, true);
12618
12619 for(int32_t i=0; i<256; i++)
12620 {
12621 byte color=unpackbuf[i];
12622 for(int32_t j=0; j<16; j++)
12623 {
12624 if(massRecolorSrc8Bit[j]==color)
12625 {
12626 color=massRecolorDest8Bit[j];
12627 break;
12628 }
12629 }
12630 buf[i]=color;
12631 }
12632
12633 pack_tile(newtilebuf, buf, tile);
12634 }
12635
12636 static void massRecolorApply(int32_t tile)
12637 {
12638 if(massRecolorIgnoreBlank && blank_tile_table[tile])
12639 return;
12640
12641 if(massRecolorType==MR_4BIT)
12642 massRecolorApply4Bit(tile);
12643 else // 8-bit
12644 {
12645 if(newtilebuf[tile].format==tf4Bit)
12646 return;
12647 massRecolorApply8Bit(tile);
12648 }
12649 }
12650
12651 static void massRecolorReset4Bit()
12652 {
12653 for(int32_t i=0; i<16; i++)
12654 massRecolorDest4Bit[i]=i;
12655 recolor_4bit_dlg[MR4_DEST_COLORS].flags|=D_DIRTY;
12656 }
12657
12658 static void massRecolorReset8Bit()
12659 {
12660 for(int32_t i=0; i<16; i++)
12661 {
12662 massRecolorSrc8Bit[i]=0;
12663 massRecolorDest8Bit[i]=0;
12664 }
12665
12666 recolor_8bit_dlg[MR8_SRC_COLORS].flags|=D_DIRTY;
12667 recolor_8bit_dlg[MR8_DEST_COLORS].flags|=D_DIRTY;
12668 }
12669
12670 8 void center_zq_tiles_dialogs()
12671 {
12672 8 jwin_center_dialog(create_relational_tiles_dlg);
12673 8 jwin_center_dialog(icon_dlg);
12674 8 jwin_center_dialog(leech_dlg);
12675 8 jwin_center_dialog(move_textbox_list_dlg);
12676 8 jwin_center_dialog(recolor_4bit_dlg);
12677 8 jwin_center_dialog(recolor_8bit_dlg);
12678 8 }
12679
12680 //.ZCOMBO
12681
12682 int32_t readcombo_loop(PACKFILE* f, word section_version, newcombo& temp_combo);
12683 int32_t writecombo_loop(PACKFILE *f, word section_version, newcombo const& tmp_cmb);
12684
12685 int32_t readcombofile_old(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t zversion,
12686 dword section_version, int32_t index, int32_t count)
12687 {
12688 byte tempbyte;
12689 newcombo temp_combo;
12690 for ( int32_t tilect = 0; tilect < count; tilect++ )
12691 {
12692 int32_t temp_trigflags[3] = {0};
12693 temp_combo.clear();
12694 combo_trigger& temp_trigger = temp_combo.triggers.emplace_back();
12695 if(!p_igetw(&temp_combo.tile,f))
12696 {
12697 return 0;
12698 }
12699 temp_combo.o_tile = temp_combo.tile;
12700
12701 if(!p_getc(&temp_combo.flip,f))
12702 {
12703 return 0;
12704 }
12705
12706 if(!p_getc(&temp_combo.walk,f))
12707 {
12708 return 0;
12709 }
12710
12711 if(!p_getc(&temp_combo.type,f))
12712 {
12713 return 0;
12714 }
12715
12716 if(!p_getc(&temp_combo.csets,f))
12717 {
12718 return 0;
12719 }
12720
12721 if(!p_getc(&temp_combo.frames,f))
12722 {
12723 return 0;
12724 }
12725
12726 if(!p_getc(&temp_combo.speed,f))
12727 {
12728 return 0;
12729 }
12730
12731 if(!p_igetw(&temp_combo.nextcombo,f))
12732 {
12733 return 0;
12734 }
12735
12736 if(!p_getc(&temp_combo.nextcset,f))
12737 {
12738 return 0;
12739 }
12740
12741 if(!p_getc(&temp_combo.flag,f))
12742 {
12743 return 0;
12744 }
12745
12746 if(!p_getc(&temp_combo.skipanim,f))
12747 {
12748 return 0;
12749 }
12750
12751 if(!p_igetw(&temp_combo.nexttimer,f))
12752 {
12753 return 0;
12754 }
12755
12756 if(!p_getc(&temp_combo.skipanimy,f))
12757 {
12758 return 0;
12759 }
12760
12761 if(!p_getc(&temp_combo.animflags,f))
12762 {
12763 return 0;
12764 }
12765
12766 //2.55 starts here
12767 if ( zversion >= 0x255 )
12768 {
12769 if ( section_version >= 12 )
12770 {
12771 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12772 {
12773 if(!p_igetl(&temp_combo.attributes[q],f))
12774 {
12775 return 0;
12776 }
12777 }
12778 if(!p_igetl(&temp_combo.usrflags,f))
12779 {
12780 return 0;
12781 }
12782 for ( int32_t q = 0; q < 3; q++ )
12783 {
12784 if(!p_igetl(&temp_trigflags[q],f))
12785 return 0;
12786 }
12787
12788 if(!p_igetl(&temp_trigger.triggerlevel,f))
12789 {
12790 return 0;
12791 }
12792 if(section_version >= 22)
12793 {
12794 if(!p_getc(&temp_trigger.triggerbtn,f))
12795 {
12796 return 0;
12797 }
12798 }
12799 if(section_version < 23)
12800 {
12801 switch(temp_combo.type) // TRIGFLAG_CMBTYPEFX now required for combotype-specific effects
12802 {
12803 case cSCRIPT1: case cSCRIPT2: case cSCRIPT3: case cSCRIPT4: case cSCRIPT5:
12804 case cSCRIPT6: case cSCRIPT7: case cSCRIPT8: case cSCRIPT9: case cSCRIPT10:
12805 case cTRIGGERGENERIC: case cCSWITCH:
12806 temp_trigflags[TRIGFLAG_CMBTYPEFX/32] |= 1 << (TRIGFLAG_CMBTYPEFX%32);
12807 }
12808 }
12809 if(section_version >= 24)
12810 {
12811 if(!p_getc(&temp_trigger.triggeritem,f))
12812 {
12813 return 0;
12814 }
12815 if(!p_getc(&tempbyte, f))
12816 return 0;
12817 temp_trigger.trigtimer = tempbyte;
12818 }
12819 if(section_version >= 25)
12820 {
12821 if(!p_getc(&temp_trigger.trigsfx,f))
12822 {
12823 return 0;
12824 }
12825 }
12826 else
12827 {
12828 switch(temp_combo.type)
12829 {
12830 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
12831 if(!(temp_combo.usrflags & cflag3))
12832 temp_combo.attribytes[3] = WAV_DOOR;
12833 temp_combo.usrflags &= ~cflag3;
12834 break;
12835 }
12836 }
12837 if(section_version < 26)
12838 {
12839 if(temp_combo.type == cARMOS)
12840 {
12841 if(temp_combo.usrflags & cflag1)
12842 temp_combo.usrflags |= cflag3;
12843 }
12844 }
12845 if(section_version >= 27)
12846 {
12847 if(!p_igetl(&temp_trigger.trigchange,f))
12848 {
12849 return qe_invalid;
12850 }
12851 }
12852 else
12853 {
12854 if(temp_trigflags[0] & 0x00040000) //'next'
12855 temp_trigger.trigchange = 1;
12856 else if(temp_trigflags[0] & 0x00080000) //'prev'
12857 temp_trigger.trigchange = -1;
12858 else temp_trigger.trigchange = 0;
12859 temp_trigflags[0] &= ~(0x00040000|0x00080000);
12860 }
12861 if(section_version >= 29)
12862 {
12863 if(!p_igetw(&temp_trigger.trigprox,f))
12864 {
12865 return qe_invalid;
12866 }
12867 if(!p_getc(&tempbyte,f))
12868 return qe_invalid;
12869 temp_trigger.trigctr = tempbyte;
12870 if(!p_igetl(&temp_trigger.trigctramnt,f))
12871 {
12872 return qe_invalid;
12873 }
12874 }
12875 else
12876 {
12877 temp_trigger.trigprox = 0;
12878 temp_trigger.trigctr = 0;
12879 temp_trigger.trigctramnt = 0;
12880 }
12881 if(section_version >= 30)
12882 {
12883 if(!p_getc(&temp_trigger.triglbeam,f))
12884 {
12885 return qe_invalid;
12886 }
12887 }
12888 else temp_trigger.triglbeam = 0;
12889 if(section_version >= 31)
12890 {
12891 if(!p_getc(&temp_trigger.trigcschange,f))
12892 {
12893 return qe_invalid;
12894 }
12895 if(!p_igetw(&temp_trigger.spawnitem,f))
12896 {
12897 return qe_invalid;
12898 }
12899 if(!p_igetw(&temp_trigger.spawnenemy,f))
12900 {
12901 return qe_invalid;
12902 }
12903 if(!p_getc(&temp_trigger.exstate,f))
12904 {
12905 return qe_invalid;
12906 }
12907 if(!p_igetl(&temp_trigger.spawnip,f))
12908 {
12909 return qe_invalid;
12910 }
12911 if(!p_getc(&temp_trigger.trigcopycat,f))
12912 {
12913 return qe_invalid;
12914 }
12915 }
12916 else
12917 {
12918 temp_trigger.trigcschange = 0;
12919 temp_trigger.spawnitem = 0;
12920 temp_trigger.spawnenemy = 0;
12921 temp_trigger.exstate = -1;
12922 temp_trigger.spawnip = 0;
12923 temp_trigger.trigcopycat = 0;
12924 }
12925 if(section_version >= 32)
12926 {
12927 if(!p_getc(&temp_trigger.trigcooldown,f))
12928 {
12929 return qe_invalid;
12930 }
12931 }
12932 else
12933 {
12934 temp_trigger.trigcooldown = 0;
12935 }
12936 char label[12];
12937 label[11] = '\0';
12938 for ( int32_t q = 0; q < 11; q++ )
12939 {
12940 if(!p_getc(&label[q],f))
12941 {
12942 return 0;
12943 }
12944 }
12945 temp_combo.label = label;
12946 }
12947 if ( section_version >= 13 )
12948 {
12949 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12950 {
12951 if(!p_getc(&temp_combo.attribytes[q],f))
12952 {
12953 return 0;
12954 }
12955 }
12956
12957 }
12958 }
12959
12960 if ( !(skip && (index+(tilect-1)) < skip) ) //is -1 still needed here?
12961 {
12962 if ( !nooverwrite || combobuf[index+tilect].is_blank() )
12963 {
12964 combobuf[index+(tilect)] = temp_combo;
12965 }
12966 }
12967
12968 temp_trigger.trigger_flags.clear();
12969 for(size_t q = 0; q < 32*3; ++q)
12970 {
12971 auto ind = q/32;
12972 auto bit = 1<<(q%32);
12973 if(temp_trigflags[ind] & bit)
12974 temp_trigger.trigger_flags.set(q, true);
12975 }
12976 }
12977
12978 return 1;
12979 }
12980
12981 int32_t readcombofile(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t start)
12982 {
12983 dword section_version=0;
12984 int32_t zversion = 0;
12985 int32_t zbuild = 0;
12986
12987 if(!p_igetl(&zversion,f))
12988 {
12989 return 0;
12990 }
12991 if(!p_igetl(&zbuild,f))
12992 {
12993 return 0;
12994 }
12995 if(!p_igetw(&section_version,f))
12996 {
12997 return 0;
12998 }
12999 if(!read_deprecated_section_cversion(f))
13000 {
13001 return 0;
13002 }
13003
13004 if ( zversion > ZELDA_VERSION )
13005 {
13006 al_trace("Cannot read .zcombo packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13007 return 0;
13008 }
13009
13010 else if ( ( section_version > V_COMBOS ))
13011 {
13012 al_trace("Cannot read .zcombo packfile made using V_COMBOS (%d)\n", section_version);
13013 return 0;
13014
13015 }
13016 else
13017 {
13018 al_trace("Reading a .zcombo packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13019 }
13020
13021 int32_t index = 0;
13022 int32_t count = 0;
13023
13024 //tile id
13025 if(!p_igetl(&index,f))
13026 {
13027 return 0;
13028 }
13029 if(start > -1) index = start;
13030
13031 //tile count
13032 if(!p_igetl(&count,f))
13033 {
13034 return 0;
13035 }
13036 reset_combo_animations();
13037 reset_combo_animations2();
13038
13039 if(section_version < 33)
13040 return readcombofile_old(f,skip,nooverwrite,zversion,section_version,index,count);
13041
13042 newcombo temp_combo;
13043 size_t end = index+count;
13044 for ( size_t q = index; q < end; q++ )
13045 {
13046 auto ret = readcombo_loop(f,section_version,temp_combo);
13047 if(ret) return 0;
13048
13049 if ( !(skip && q-1 < skip) )
13050 {
13051 if ( !nooverwrite || combobuf[q].is_blank() )
13052 {
13053 combobuf[q] = temp_combo;
13054 }
13055 }
13056 }
13057
13058 return 1;
13059 }
13060 int32_t readcombofile_to_location(PACKFILE *f, int32_t start, byte nooverwrite, int32_t skip)
13061 {
13062 return readcombofile(f,skip,nooverwrite,start);
13063 }
13064 int32_t writecombofile(PACKFILE *f, int32_t index, int32_t count)
13065 {
13066 dword section_version=V_COMBOS;
13067 int32_t zversion = ZELDA_VERSION;
13068 int32_t zbuild = VERSION_BUILD;
13069
13070 if(!p_iputl(zversion,f))
13071 {
13072 return 0;
13073 }
13074 if(!p_iputl(zbuild,f))
13075 {
13076 return 0;
13077 }
13078 if(!p_iputw(section_version,f))
13079 {
13080 return 0;
13081 }
13082
13083 if(!write_deprecated_section_cversion(section_version,f))
13084 {
13085 return 0;
13086 }
13087
13088 //start tile id
13089 if(!p_iputl(index,f))
13090 {
13091 return 0;
13092 }
13093
13094 //count
13095 if(!p_iputl(count,f))
13096 {
13097 return 0;
13098 }
13099 reset_combo_animations();
13100 reset_combo_animations2();
13101 size_t end = index+count;
13102 for(size_t q = index; q < end; ++q)
13103 {
13104 if(writecombo_loop(f, section_version, combobuf[q]))
13105 return 0;
13106 }
13107
13108 return 1;
13109
13110 }
13111
13112 //.ZALIAS
13113
13114
13115 //.ZALIAS
13116
13117 int32_t readcomboaliasfile(PACKFILE *f)
13118 {
13119 dword section_version=0;
13120 int32_t zversion = 0;
13121 int32_t zbuild = 0;
13122 word tempword = 0;
13123
13124 if(!p_igetl(&zversion,f))
13125 {
13126 return 0;
13127 }
13128 if(!p_igetl(&zbuild,f))
13129 {
13130 return 0;
13131 }
13132 if(!p_igetw(&section_version,f))
13133 {
13134 return 0;
13135 }
13136 if(!read_deprecated_section_cversion(f))
13137 {
13138 return 0;
13139 }
13140 al_trace("readoneweapon section_version: %d\n", section_version);
13141
13142 if ( zversion > ZELDA_VERSION )
13143 {
13144 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13145 return 0;
13146 }
13147
13148 else if ( ( section_version > V_COMBOALIASES ))
13149 {
13150 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d)\n", section_version);
13151 return 0;
13152
13153 }
13154 else
13155 {
13156 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13157 }
13158
13159 int32_t index = 0;
13160 int32_t count = 0;
13161 int32_t count2 = 0;
13162 byte tempcset = 0;
13163
13164 //tile id
13165 if(!p_igetl(&index,f))
13166 {
13167 return 0;
13168 }
13169 al_trace("Reading combo: index(%d)\n", index);
13170
13171 //tile count
13172 if(!p_igetl(&count,f))
13173 {
13174 return 0;
13175 }
13176 al_trace("Reading combo: count(%d)\n", count);
13177
13178 combo_alias temp_alias;
13179
13180 for ( int32_t tilect = 0; tilect < count; tilect++ )
13181 {
13182 temp_alias.clear();
13183 if(!p_igetw(&temp_alias.combo,f))
13184 {
13185 return 0;
13186 }
13187
13188 if(!p_getc(&temp_alias.cset,f))
13189 {
13190 return 0;
13191 }
13192
13193
13194
13195 if(!p_igetl(&count2,f))
13196 {
13197 return 0;
13198 }
13199 al_trace("Read, Combo alias count is: %d\n", count2);
13200 if(!p_getc(&temp_alias.width,f))
13201 {
13202 return 0;
13203 }
13204
13205 if(!p_getc(&temp_alias.height,f))
13206 {
13207 return 0;
13208 }
13209
13210 if(!p_getc(&temp_alias.layermask,f))
13211 {
13212 return 0;
13213 }
13214 //These values are flexible, and may differ in size, so we delete them
13215 //and recreate them at the correct size on the pointer.
13216 temp_alias.combos.clear();
13217 temp_alias.csets.clear();
13218 for(int32_t k=0; k<count2; k++)
13219 {
13220 if(!p_igetw(&tempword,f))
13221 {
13222 return 0;
13223 }
13224 else
13225 {
13226
13227
13228 temp_alias.combos[k] = tempword;
13229 }
13230 }
13231
13232 for(int32_t k=0; k<count2; k++)
13233 {
13234 if(!p_getc(&tempcset,f))
13235 //if(!p_getc(&temp_alias.csets[k],f))
13236 {
13237 return 0;
13238 }
13239 else
13240 {
13241
13242 temp_alias.csets[k] = tempcset;
13243 }
13244 }
13245 combo_aliases[index+(tilect)] = temp_alias;
13246 }
13247
13248 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
13249
13250
13251 return 1;
13252
13253 }
13254
13255 int32_t readcomboaliasfile_to_location(PACKFILE *f, int32_t start)
13256 {
13257 dword section_version=0;
13258 int32_t zversion = 0;
13259 int32_t zbuild = 0;
13260
13261 if(!p_igetl(&zversion,f))
13262 {
13263 return 0;
13264 }
13265 if(!p_igetl(&zbuild,f))
13266 {
13267 return 0;
13268 }
13269 if(!p_igetw(&section_version,f))
13270 {
13271 return 0;
13272 }
13273 if(!read_deprecated_section_cversion(f))
13274 {
13275 return 0;
13276 }
13277 al_trace("readcomboaliasfile_to_location section_version: %d\n", section_version);
13278
13279 if ( zversion > ZELDA_VERSION )
13280 {
13281 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13282 return 0;
13283 }
13284 else if ( ( section_version > V_COMBOALIASES ))
13285 {
13286 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d)\n", section_version);
13287 return 0;
13288
13289 }
13290 else
13291 {
13292 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13293 }
13294
13295 int32_t index = 0;
13296 int32_t count = 0;
13297 int32_t count2 = 0;
13298 byte tempcset = 0;
13299 word tempword = 0;
13300
13301
13302 //tile id
13303 if(!p_igetl(&index,f))
13304 {
13305 return 0;
13306 }
13307 al_trace("Reading tile: index(%d)\n", index);
13308
13309 //tile count
13310 if(!p_igetl(&count,f))
13311 {
13312 return 0;
13313 }
13314 al_trace("Reading tile: count(%d)\n", count);
13315
13316
13317 combo_alias temp_alias;
13318
13319 for ( int32_t tilect = 0; tilect < count; tilect++ )
13320 {
13321 temp_alias.clear();
13322 if(!p_igetw(&temp_alias.combo,f))
13323 {
13324 return 0;
13325 }
13326
13327 if(!p_getc(&temp_alias.cset,f))
13328 {
13329 return 0;
13330 }
13331
13332 int32_t count2 = 0;
13333
13334 if(!p_igetl(&count2,f))
13335 {
13336 return 0;
13337 }
13338
13339 if(!p_getc(&temp_alias.width,f))
13340 {
13341 return 0;
13342 }
13343
13344 if(!p_getc(&temp_alias.height,f))
13345 {
13346 return 0;
13347 }
13348
13349 if(!p_getc(&temp_alias.layermask,f))
13350 {
13351 return 0;
13352 }
13353 //These values are flexible, and may differ in size, so we delete them
13354 //and recreate them at the correct size on the pointer.
13355 temp_alias.combos.clear();
13356 temp_alias.csets.clear();
13357
13358 for(int32_t k=0; k<count2; k++)
13359 {
13360 if(!p_igetw(&tempword,f))
13361 {
13362 return 0;
13363 }
13364 else
13365 {
13366 temp_alias.combos[k] = tempword;
13367 }
13368 }
13369
13370 for(int32_t k=0; k<count2; k++)
13371 {
13372 if(!p_getc(&tempcset,f))
13373 {
13374 return 0;
13375 }
13376 else
13377 {
13378 temp_alias.csets[k] = tempcset;
13379 }
13380 }
13381
13382 if ( start+(tilect) < MAXCOMBOALIASES )
13383 {
13384 combo_aliases[start + (tilect)] = temp_alias;
13385 }
13386 }
13387 return 1;
13388 }
13389 int32_t writecomboaliasfile(PACKFILE *f, int32_t index, int32_t count)
13390 {
13391 al_trace("Running writecomboaliasfile\n");
13392 dword section_version=V_COMBOALIASES;
13393 int32_t zversion = ZELDA_VERSION;
13394 int32_t zbuild = VERSION_BUILD;
13395
13396 if(!p_iputl(zversion,f))
13397 {
13398 return 0;
13399 }
13400 if(!p_iputl(zbuild,f))
13401 {
13402 return 0;
13403 }
13404 if(!p_iputw(section_version,f))
13405 {
13406 return 0;
13407 }
13408
13409 if(!write_deprecated_section_cversion(section_version,f))
13410 {
13411 return 0;
13412 }
13413
13414 //start tile id
13415 if(!p_iputl(index,f))
13416 {
13417 return 0;
13418 }
13419
13420 //count
13421 if(!p_iputl(count,f))
13422 {
13423 return 0;
13424 }
13425
13426 for ( int32_t tilect = 0; tilect < count; tilect++ )
13427 {
13428
13429 if(!p_iputw(combo_aliases[index+(tilect)].combo,f))
13430 {
13431 return 0;
13432 }
13433
13434 if(!p_putc(combo_aliases[index+(tilect)].cset,f))
13435 {
13436 return 0;
13437 }
13438
13439 int32_t count2 = ((combo_aliases[index+(tilect)].width+1)*(combo_aliases[index+(tilect)].height+1))*(comboa_lmasktotal(combo_aliases[index+(tilect)].layermask)+1);
13440
13441 if(!p_iputl(count2,f))
13442 {
13443 return 0;
13444 }
13445 al_trace("Write`, Combo alias count is: %d\n", count2);
13446
13447 if(!p_putc(combo_aliases[index+(tilect)].width,f))
13448 {
13449 return 0;
13450 }
13451
13452 if(!p_putc(combo_aliases[index+(tilect)].height,f))
13453 {
13454 return 0;
13455 }
13456
13457 if(!p_putc(combo_aliases[index+(tilect)].layermask,f))
13458 {
13459 return 0;
13460 }
13461
13462 for(int32_t k=0; k<count2; k++)
13463 {
13464 if(!p_iputw(combo_aliases[index+(tilect)].combos[k],f))
13465 {
13466 return 0;
13467 }
13468 }
13469
13470 for(int32_t k=0; k<count2; k++)
13471 {
13472 if(!p_putc(combo_aliases[index+(tilect)].csets[k],f))
13473 {
13474 return 0;
13475 }
13476 }
13477 }
13478
13479 return 1;
13480
13481 }
13482